aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/flatbuffers
diff options
context:
space:
mode:
authorreshilkin <reshilkin@yandex-team.com>2023-08-11 12:01:29 +0300
committerreshilkin <reshilkin@yandex-team.com>2023-08-11 13:00:03 +0300
commit5894c3ce50a49a9f9bc1c0316e2ef0708e3a7ef8 (patch)
tree624e56690fe689e569d05612fa0e92f2c5bdb75b /contrib/libs/flatbuffers
parent1eb895279c52b0d2505a31b79ad326b56d0b2681 (diff)
downloadydb-5894c3ce50a49a9f9bc1c0316e2ef0708e3a7ef8.tar.gz
Update contrib/libs/flatbuffers to 23.5.9
Diffstat (limited to 'contrib/libs/flatbuffers')
-rw-r--r--contrib/libs/flatbuffers/CHANGELOG.md150
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt1
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt1
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt1
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt1
-rw-r--r--contrib/libs/flatbuffers/LICENSE (renamed from contrib/libs/flatbuffers/LICENSE.txt)0
-rw-r--r--contrib/libs/flatbuffers/README.md80
-rw-r--r--contrib/libs/flatbuffers/SECURITY.md11
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt9
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt9
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt9
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt9
-rw-r--r--contrib/libs/flatbuffers/flatc/ya.make12
-rw-r--r--contrib/libs/flatbuffers/grpc/README.md5
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/config.h40
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc420
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h40
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc762
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h47
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc282
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc4
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h1
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h5
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc10
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h38
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc88
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h37
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/allocator.h68
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/array.h256
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/base.h116
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/buffer.h199
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/buffer_ref.h53
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/code_generator.h82
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/code_generators.h5
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/default_allocator.h64
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/detached_buffer.h114
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/file_manager.h48
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h1471
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h2737
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h27
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatc.h95
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h361
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/idl.h338
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/reflection.h35
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h869
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h446
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/string.h64
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/struct.h53
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/table.h188
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/util.h72
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/vector.h400
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/vector_downward.h288
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/verifier.h330
-rw-r--r--contrib/libs/flatbuffers/src/annotated_binary_text_gen.cpp461
-rw-r--r--contrib/libs/flatbuffers/src/annotated_binary_text_gen.h75
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_gen.h206
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp674
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_gen_lua.h33
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp692
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_gen_nim.h33
-rw-r--r--contrib/libs/flatbuffers/src/bfbs_namer.h51
-rw-r--r--contrib/libs/flatbuffers/src/binary_annotator.cpp1519
-rw-r--r--contrib/libs/flatbuffers/src/binary_annotator.h406
-rw-r--r--contrib/libs/flatbuffers/src/code_generators.cpp114
-rw-r--r--contrib/libs/flatbuffers/src/file_binary_writer.cpp49
-rw-r--r--contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp49
-rw-r--r--contrib/libs/flatbuffers/src/file_writer.cpp47
-rw-r--r--contrib/libs/flatbuffers/src/flatc.cpp942
-rw-r--r--contrib/libs/flatbuffers/src/flatc_main.cpp196
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_binary.cpp92
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_binary.h32
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp.cpp1948
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp65
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.h13
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_csharp.cpp799
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_csharp.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_dart.cpp1032
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_dart.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_fbs.cpp325
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_fbs.h28
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_go.cpp708
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_go.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_grpc.cpp19
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_java.cpp1340
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_java.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp146
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_json_schema.h32
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp351
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_kotlin.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lobster.cpp99
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lobster.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lua.cpp99
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lua.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_php.cpp120
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_php.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_python.cpp1538
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_python.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_rust.cpp1696
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_rust.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_swift.cpp1308
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_swift.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_text.cpp243
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_text.h29
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_ts.cpp1220
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_ts.h32
-rw-r--r--contrib/libs/flatbuffers/src/idl_namer.h177
-rw-r--r--contrib/libs/flatbuffers/src/idl_parser.cpp1371
-rw-r--r--contrib/libs/flatbuffers/src/namer.h266
-rw-r--r--contrib/libs/flatbuffers/src/reflection.cpp526
-rw-r--r--contrib/libs/flatbuffers/src/util.cpp243
-rw-r--r--contrib/libs/flatbuffers/ya.make13
112 files changed, 23124 insertions, 9532 deletions
diff --git a/contrib/libs/flatbuffers/CHANGELOG.md b/contrib/libs/flatbuffers/CHANGELOG.md
new file mode 100644
index 0000000000..4c627ed365
--- /dev/null
+++ b/contrib/libs/flatbuffers/CHANGELOG.md
@@ -0,0 +1,150 @@
+# Flatbuffers Change Log
+
+All major or breaking changes will be documented in this file, as well as any
+new features that should be highlighted. Minor fixes or improvements are not
+necessarily listed.
+
+## [23.5.9 (May 9 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.9)
+
+* 64-bit support for C++ (#7935)
+
+## [23.5.8 (May 8 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.8)
+
+* add key_field to compiled tests
+* Add golden language directory
+* Rework cmake flatc codegeneration (#7938)
+* remove defining generated files in test srcs
+* Add binary schema reflection (#7932)
+* Migrate from rules_nodejs to rules_js/rules_ts (take 2) (#7928)
+* `flat_buffers.dart`: mark const variable finals for internal Dart linters
+* fixed some windows warnings (#7929)
+* inject no long for FBS generation to remove logs in flattests (#7926)
+* Revert "Migrate from rules_nodejs to rules_js/rules_ts (#7923)" (#7927)
+* Migrate from rules_nodejs to rules_js/rules_ts (#7923)
+* Only generate @kotlin.ExperimentalUnsigned annotation on create*Vector methods having an unsigned array type parameter. (#7881)
+* additional check for absl::string_view availability (#7897)
+* Optionally generate Python type annotations (#7858)
+* Replace deprecated command with environment file (#7921)
+* drop glibc from runtime dependencies (#7906)
+* Make JSON supporting advanced union features (#7869)
+* Allow to use functions from `BuildFlatBuffers.cmake` from a flatbuffers installation installed with CMake. (#7912)
+* TS/JS: Use TypeError instead of Error when appropriate (#7910)
+* Go: make generated code more compliant to "go fmt" (#7907)
+* Support file_identifier in Go (#7904)
+* Optionally generate type prefixes and suffixes for python code (#7857)
+* Go: add test for FinishWithFileIdentifier (#7905)
+* Fix go_sample.sh (#7903)
+* [TS/JS] Upgrade dependencies (#7889)
+* Add a FileWriter interface (#7821)
+* TS/JS: Use minvalue from enum if not found (#7888)
+* [CS] Verifier (#7850)
+* README.md: PyPI case typo (#7880)
+* Update go documentation link to point to root module (#7879)
+* use Bool for flatbuffers bool instead of Byte (#7876)
+* fix using null string in vector (#7872)
+* Add `flatbuffers-64` branch to CI for pushes
+* made changes to the rust docs so they would compile. new_with_capacity is deprecated should use with_capacity, get_root_as_monster should be root_as_monster (#7871)
+* Adding comment for code clarification (#7856)
+* ToCamelCase() when kLowerCamel now converts first char to lower. (#7838)
+* Fix help output for --java-checkerframework (#7854)
+* Update filename to README.md and improve formatting (#7855)
+* Update stale.yml
+* Updated remaining usages of LICENSE.txt
+
+## [23.3.3 (Mar 3 2023)](https://github.com/google/flatbuffers/releases/tag/v23.3.3)
+
+* Refactoring of `flatc` generators to use an interface (#7797).
+
+* Removed legacy cmake support and set min to 3.8 (#7801).
+
+## [23.1.21 (Jan 21 2023)](https://github.com/google/flatbuffers/releases/tag/v23.1.20)
+
+* Reworked entry points for Typescript/Javascript and compatibility for single
+ file build (#7510)
+
+## [23.1.20 (Jan 20 2023)](https://github.com/google/flatbuffers/releases/tag/v23.1.20)
+
+* Removed go.mod files after some versioning issues were being report (#7780).
+
+## [23.1.4 (Jan 4 2023)](https://github.com/google/flatbuffers/releases/tag/v23.1.4)
+
+* Major release! Just kidding, we are continuing the
+ [versioning scheme](https://github.com/google/flatbuffers/wiki/Versioning) of
+ using a date to signify releases. This results in the first release of the new
+ year to bump the tradition major version field.
+
+* Go minimum version is now 1.19 (#7720) with the addition of Go modules.
+
+* Added CI support for Big Endian regression testing (#7707).
+
+* Fixed `getFullyQualifiedName` in typescript to return name delimited by '.'
+ instead of '_' (#7730).
+
+* Fixed the versioning scheme to not include leading zeros which are not
+ consistently handled by every package manager. Only the last release
+ (12.12.06) should have suffered from this.
+
+## [22.12.06 (Dec 06 2022)](https://github.com/google/flatbuffers/releases/tag/v22.12.06)
+
+* Bug fixing release, no major changes.
+
+## [22.10.25 (Oct 25 2022)](https://github.com/google/flatbuffers/releases/tag/v22.10.25)
+
+* Added Nim language support with generator and runtime libraries (#7534).
+
+## [22.9.29 (Sept 29 2022)](https://github.com/google/flatbuffers/releases/tag/v22.9.29)
+
+* Rust soundness fixes to avoid the crate from bing labelled unsafe (#7518).
+
+## [22.9.24 (Sept 24 2022)](https://github.com/google/flatbuffers/releases/tag/v22.9.24)
+
+* 20 Major releases in a row? Nope, we switched to a new
+ [versioning scheme](https://github.com/google/flatbuffers/wiki/Versioning)
+ that is based on date.
+
+* Python supports fixed size arrays now (#7529).
+
+* Behavior change in how C++ object API uses `UnPackTo`. The original intent of
+ this was to reduce allocations by reusing an existing object to pack data
+ into. At some point, this logic started to merge the states of the two objects
+ instead of clearing the state of the packee. This change goes back to the
+ original intention, the packed object is cleared when getting data packed into
+ it (#7527).
+
+* Fixed a bug in C++ alignment that was using `sizeof()` instead of the intended
+ `AlignOf()` for structs (#7520).
+
+* C# has an
+ [official Nuget package](https://www.nuget.org/packages/Google.FlatBuffers)
+ now (#7496).
+
+## 2.0.8 (Aug 29 2022)
+
+* Fix for `--keep-prefix` the was generating the wrong include statements for
+ C++ (#7469). The bug was introduced in 2.0.7.
+
+* Added the `Verifier::Options` option struct to allow specifying runtime
+ configuration settings for the verifier (#7489). This allows to skip verifying
+ nested flatbuffers, a on-by-default change that was introduced in 2.0.7. This
+ deprecates the existing `Verifier` constructor, which may be removed in a
+ future version.
+
+* Refactor of `tests/test.cpp` that lead to ~10% speedup in compilation of the
+ entire project (#7487).
+
+## 2.0.7 (Aug 22 2022)
+
+* This is the first version with an explicit change log, so all the previous
+ features will not be listed.
+
+* Verifier now checks that buffers are at least the minimum size required to be
+ a flatbuffers (12 bytes). This includes nested flatbuffers, which previously
+ could be declared valid at size 0.
+
+* Annotated binaries. Given a flatbuffer binary and a schema (or binary schema)
+ one can generate an annotated flatbuffer (.afb) to describe each byte in the
+ binary with schema metadata and value.
+
+* First binary schema generator (Lua) to generate Lua code via a .bfbs file.
+ This is mostly an implementation detail of flatc internals, but will be slowly
+ applied to the other language generators.
diff --git a/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt
index 69394c43b6..506517c695 100644
--- a/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt
@@ -18,6 +18,7 @@ target_include_directories(contrib-libs-flatbuffers PRIVATE
)
target_link_libraries(contrib-libs-flatbuffers PUBLIC
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(contrib-libs-flatbuffers PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
diff --git a/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt b/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt
index a176d50a06..8bf1b6647c 100644
--- a/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt
@@ -19,6 +19,7 @@ target_include_directories(contrib-libs-flatbuffers PRIVATE
target_link_libraries(contrib-libs-flatbuffers PUBLIC
contrib-libs-linux-headers
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(contrib-libs-flatbuffers PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
diff --git a/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt
index a176d50a06..8bf1b6647c 100644
--- a/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt
@@ -19,6 +19,7 @@ target_include_directories(contrib-libs-flatbuffers PRIVATE
target_link_libraries(contrib-libs-flatbuffers PUBLIC
contrib-libs-linux-headers
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(contrib-libs-flatbuffers PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
diff --git a/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt
index 69394c43b6..506517c695 100644
--- a/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt
@@ -18,6 +18,7 @@ target_include_directories(contrib-libs-flatbuffers PRIVATE
)
target_link_libraries(contrib-libs-flatbuffers PUBLIC
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(contrib-libs-flatbuffers PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
diff --git a/contrib/libs/flatbuffers/LICENSE.txt b/contrib/libs/flatbuffers/LICENSE
index d645695673..d645695673 100644
--- a/contrib/libs/flatbuffers/LICENSE.txt
+++ b/contrib/libs/flatbuffers/LICENSE
diff --git a/contrib/libs/flatbuffers/README.md b/contrib/libs/flatbuffers/README.md
new file mode 100644
index 0000000000..1fb2fe0c66
--- /dev/null
+++ b/contrib/libs/flatbuffers/README.md
@@ -0,0 +1,80 @@
+![logo](http://google.github.io/flatbuffers/fpl_logo_small.png) FlatBuffers
+===========
+
+![Build status](https://github.com/google/flatbuffers/actions/workflows/build.yml/badge.svg?branch=master)
+[![BuildKite status](https://badge.buildkite.com/7979d93bc6279aa539971f271253c65d5e8fe2fe43c90bbb25.svg)](https://buildkite.com/bazel/flatbuffers)
+[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/flatbuffers.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:flatbuffers)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers/badge)](https://api.securityscorecards.dev/projects/github.com/google/flatbuffers)
+[![Join the chat at https://gitter.im/google/flatbuffers](https://badges.gitter.im/google/flatbuffers.svg)](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Discord Chat](https://img.shields.io/discord/656202785926152206.svg)](https:///discord.gg/6qgKs3R)
+[![Twitter Follow](https://img.shields.io/twitter/follow/wvo.svg?style=social)](https://twitter.com/wvo)
+[![Twitter Follow](https://img.shields.io/twitter/follow/dbaileychess.svg?style=social)](https://twitter.com/dbaileychess)
+
+
+**FlatBuffers** is a cross platform serialization library architected for
+maximum memory efficiency. It allows you to directly access serialized data without parsing/unpacking it first, while still having great forwards/backwards compatibility.
+
+**Go to our [landing page][] to browse our documentation.**
+
+## Supported operating systems
+- Windows
+- macOS
+- Linux
+- Android
+- And any others with a recent C++ compiler (C++ 11 and newer)
+
+## Supported programming languages
+
+Code generation and runtime libraries for many popular languages.
+
+1. C
+1. C++ - [snapcraft.io](https://snapcraft.io/flatbuffers)
+1. C# - [nuget.org](https://www.nuget.org/packages/Google.FlatBuffers)
+1. Dart - [pub.dev](https://pub.dev/packages/flat_buffers)
+1. Go - [go.dev](https://pkg.go.dev/github.com/google/flatbuffers)
+1. Java - [Maven](https://search.maven.org/artifact/com.google.flatbuffers/flatbuffers-java)
+1. JavaScript - [NPM](https://www.npmjs.com/package/flatbuffers)
+1. Kotlin
+1. Lobster
+1. Lua
+1. PHP
+1. Python - [PyPI](https://pypi.org/project/flatbuffers/)
+1. Rust - [crates.io](https://crates.io/crates/flatbuffers)
+1. Swift - [swiftpackageindex](https://swiftpackageindex.com/google/flatbuffers)
+1. TypeScript - [NPM](https://www.npmjs.com/package/flatbuffers)
+1. Nim
+
+## Versioning
+
+FlatBuffers does not follow traditional Semver versioning (see [rationale](https://github.com/google/flatbuffers/wiki/Versioning)) but rather uses a format of the date of the release.
+
+## Contribution
+
+* [FlatBuffers Issues Tracker][] to submit an issue.
+* [stackoverflow.com][] with [`flatbuffers` tag][] for any questions regarding FlatBuffers.
+
+*To contribute to this project,* see [CONTRIBUTING][].
+
+## Community
+
+* [FlatBuffers Google Group][] to discuss FlatBuffers with other developers and users.
+* [Discord Server](https:///discord.gg/6qgKs3R)
+* [Gitter](https://gitter.im/google/flatbuffers)
+
+
+## Security
+
+Please see our [Security Policy](SECURITY.md) for reporting vulnerabilities.
+
+## Licensing
+*Flatbuffers* is licensed under the Apache License, Version 2.0. See [LICENSE][] for the full license text.
+
+<br>
+
+ [CONTRIBUTING]: http://github.com/google/flatbuffers/blob/master/CONTRIBUTING.md
+ [`flatbuffers` tag]: https://stackoverflow.com/questions/tagged/flatbuffers
+ [FlatBuffers Google Group]: https://groups.google.com/forum/#!forum/flatbuffers
+ [FlatBuffers Issues Tracker]: http://github.com/google/flatbuffers/issues
+ [stackoverflow.com]: http://stackoverflow.com/search?q=flatbuffers
+ [landing page]: https://google.github.io/flatbuffers
+ [LICENSE]: https://github.com/google/flatbuffers/blob/master/LICENSE
diff --git a/contrib/libs/flatbuffers/SECURITY.md b/contrib/libs/flatbuffers/SECURITY.md
new file mode 100644
index 0000000000..c61f66f84a
--- /dev/null
+++ b/contrib/libs/flatbuffers/SECURITY.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+To report a security issue, please use http://g.co/vulnz. We use
+http://g.co/vulnz for our intake, and do coordination and disclosure here on
+GitHub (including using GitHub Security Advisory). The Google Security Team will
+respond within 5 working days of your report on g.co/vulnz.
+
+Select the `I want to report a technical security or an abuse risk related bug
+in a Google product (SQLi, XSS, etc.)` option and complete the form.
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt
index ee54cbf098..60468b3dcd 100644
--- a/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt
@@ -18,6 +18,7 @@ target_include_directories(libs-flatbuffers-flatc PRIVATE
)
target_link_libraries(libs-flatbuffers-flatc PUBLIC
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(libs-flatbuffers-flatc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -26,8 +27,16 @@ target_sources(libs-flatbuffers-flatc PRIVATE
${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/annotated_binary_text_gen.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/binary_annotator.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_binary_writer.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_writer.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_binary.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
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt
index cae0280fd9..8e7b7f0105 100644
--- a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt
@@ -19,6 +19,7 @@ target_include_directories(libs-flatbuffers-flatc PRIVATE
target_link_libraries(libs-flatbuffers-flatc PUBLIC
contrib-libs-linux-headers
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(libs-flatbuffers-flatc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -27,8 +28,16 @@ target_sources(libs-flatbuffers-flatc PRIVATE
${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/annotated_binary_text_gen.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/binary_annotator.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_binary_writer.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_writer.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_binary.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
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt
index cae0280fd9..8e7b7f0105 100644
--- a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt
@@ -19,6 +19,7 @@ target_include_directories(libs-flatbuffers-flatc PRIVATE
target_link_libraries(libs-flatbuffers-flatc PUBLIC
contrib-libs-linux-headers
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(libs-flatbuffers-flatc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -27,8 +28,16 @@ target_sources(libs-flatbuffers-flatc PRIVATE
${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/annotated_binary_text_gen.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/binary_annotator.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_binary_writer.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_writer.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_binary.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
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt
index ee54cbf098..60468b3dcd 100644
--- a/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt
@@ -18,6 +18,7 @@ target_include_directories(libs-flatbuffers-flatc PRIVATE
)
target_link_libraries(libs-flatbuffers-flatc PUBLIC
contrib-libs-cxxsupp
+ abseil-cpp-absl-base
)
target_sources(libs-flatbuffers-flatc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -26,8 +27,16 @@ target_sources(libs-flatbuffers-flatc PRIVATE
${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/annotated_binary_text_gen.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/binary_annotator.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_binary_writer.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/file_writer.cpp
${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_binary.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
diff --git a/contrib/libs/flatbuffers/flatc/ya.make b/contrib/libs/flatbuffers/flatc/ya.make
index 7186851a35..1ed0d49cba 100644
--- a/contrib/libs/flatbuffers/flatc/ya.make
+++ b/contrib/libs/flatbuffers/flatc/ya.make
@@ -6,6 +6,10 @@ WITHOUT_LICENSE_TEXTS()
LICENSE(Apache-2.0)
+PEERDIR(
+ contrib/restricted/abseil-cpp/absl/base
+)
+
ADDINCL(
contrib/libs/flatbuffers/grpc
contrib/libs/flatbuffers/include
@@ -28,8 +32,16 @@ SRCS(
grpc/src/compiler/python_generator.cc
grpc/src/compiler/swift_generator.cc
grpc/src/compiler/ts_generator.cc
+ src/annotated_binary_text_gen.cpp
+ src/bfbs_gen_lua.cpp
+ src/bfbs_gen_nim.cpp
+ src/binary_annotator.cpp
src/code_generators.cpp
+ src/file_binary_writer.cpp
+ src/file_name_saving_file_manager.cpp
+ src/file_writer.cpp
src/flatc.cpp
+ src/idl_gen_binary.cpp
src/idl_gen_cpp.cpp
src/idl_gen_cpp_yandex_maps_iter.cpp
src/idl_gen_csharp.cpp
diff --git a/contrib/libs/flatbuffers/grpc/README.md b/contrib/libs/flatbuffers/grpc/README.md
index 685003f92b..f46258fcb1 100644
--- a/contrib/libs/flatbuffers/grpc/README.md
+++ b/contrib/libs/flatbuffers/grpc/README.md
@@ -32,9 +32,8 @@ $bazel test src/compiler/...
### 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`
+1. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
+2. `make test ARGS=-V`
For Bazel users:
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/config.h b/contrib/libs/flatbuffers/grpc/src/compiler/config.h
deleted file mode 100644
index 4adc594377..0000000000
--- a/contrib/libs/flatbuffers/grpc/src/compiler/config.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * 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
index 8dd408830c..fd635f2fa5 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -1,65 +1,31 @@
-/*
- *
- * 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 "src/compiler/cpp_generator.h"
#include <map>
+#include <sstream>
-#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"; }
+static grpc::string service_header_ext() { return ".grpc.fb.h"; }
-template <class T>
-grpc::string as_string(T x) {
+template<class T>
+static grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
}
-inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
+static inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
return method->ClientStreaming() && !method->ServerStreaming();
}
-inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
+static inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
return !method->ClientStreaming() && method->ServerStreaming();
}
-grpc::string FilenameIdentifier(const grpc::string &filename) {
+static grpc::string FilenameIdentifier(const grpc::string &filename) {
grpc::string result;
for (unsigned i = 0; i < filename.size(); i++) {
char c = filename[i];
@@ -74,14 +40,11 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
}
return result;
}
-} // namespace
-template <class T, size_t N>
-T *array_end(T (&array)[N]) {
- return array + N;
-}
+template<class T, size_t N>
+static T *array_end(T (&array)[N]) { return array + N; }
-void PrintIncludes(grpc_generator::Printer *printer,
+static void PrintIncludes(grpc_generator::Printer *printer,
const std::vector<grpc::string> &headers,
const Parameters &params) {
std::map<grpc::string, grpc::string> vars;
@@ -92,9 +55,7 @@ void PrintIncludes(grpc_generator::Printer *printer,
auto &s = params.grpc_search_path;
if (!s.empty()) {
vars["l"] += s;
- if (s[s.size() - 1] != '/') {
- vars["l"] += '/';
- }
+ if (s[s.size() - 1] != '/') { vars["l"] += '/'; }
}
for (auto i = headers.begin(); i != headers.end(); i++) {
@@ -103,8 +64,10 @@ void PrintIncludes(grpc_generator::Printer *printer,
}
}
+} // namespace
+
grpc::string GetHeaderPrologue(grpc_generator::File *file,
- const Parameters & /*params*/) {
+ const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -114,7 +77,7 @@ grpc::string GetHeaderPrologue(grpc_generator::File *file,
vars["filename"] = file->filename();
vars["filename_identifier"] = FilenameIdentifier(file->filename());
vars["filename_base"] = file->filename_without_ext();
- vars["message_header_ext"] = message_header_ext();
+ vars["message_header_ext"] = params.message_header_extension;
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars,
@@ -144,15 +107,16 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
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"};
+ "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");
@@ -176,7 +140,10 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
return output;
}
-void PrintHeaderClientMethodInterfaces(
+
+namespace {
+
+static 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();
@@ -187,8 +154,8 @@ void PrintHeaderClientMethodInterfaces(
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", "", ""}};
+ } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
+ { "PrepareAsync", "", "" } };
if (is_public) {
if (method->NoStreaming()) {
@@ -196,8 +163,9 @@ void PrintHeaderClientMethodInterfaces(
*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];
+ 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,
@@ -228,8 +196,9 @@ void PrintHeaderClientMethodInterfaces(
"($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];
+ 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;
@@ -262,8 +231,9 @@ void PrintHeaderClientMethodInterfaces(
"($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];
+ 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;
@@ -295,8 +265,9 @@ void PrintHeaderClientMethodInterfaces(
"$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];
+ 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;
@@ -318,8 +289,9 @@ void PrintHeaderClientMethodInterfaces(
}
} else {
if (method->NoStreaming()) {
- for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
- auto& async_prefix = async_prefixes[i];
+ 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,
@@ -334,8 +306,9 @@ void PrintHeaderClientMethodInterfaces(
"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];
+ 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(
@@ -351,8 +324,9 @@ void PrintHeaderClientMethodInterfaces(
"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];
+ 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(
@@ -367,8 +341,9 @@ void PrintHeaderClientMethodInterfaces(
"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];
+ 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(
@@ -382,7 +357,9 @@ void PrintHeaderClientMethodInterfaces(
}
}
-void PrintHeaderClientMethod(grpc_generator::Printer *printer,
+
+
+static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars,
bool is_public) {
@@ -393,8 +370,8 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
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", "", ""}};
+ } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
+ { "PrepareAsync", "", "" } };
if (is_public) {
if (method->NoStreaming()) {
@@ -402,8 +379,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
*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];
+ 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,
@@ -431,8 +409,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($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];
+ 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;
@@ -463,8 +442,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($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];
+ 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;
@@ -494,8 +474,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"$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];
+ 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;
@@ -516,8 +497,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
}
} else {
if (method->NoStreaming()) {
- for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
- auto& async_prefix = async_prefixes[i];
+ 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,
@@ -531,8 +513,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"::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];
+ 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;
@@ -547,8 +530,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"::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];
+ 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;
@@ -562,8 +546,9 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
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];
+ 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;
@@ -577,7 +562,7 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
}
}
-void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
+static void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -585,7 +570,7 @@ void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
"const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
}
-void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
+static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -619,7 +604,7 @@ void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
printer->Print(method->GetTrailingComments("//").c_str());
}
-void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
+static void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -630,7 +615,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
"class WithAsyncMethod_$Method$ : public BaseClass {\n");
printer->Print(
" private:\n"
- " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
+ "{}\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(*vars,
@@ -646,8 +632,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "$Response$* response) final override {\n"
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "$Response$* /*response*/) final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
"}\n");
@@ -667,9 +653,9 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, "
- "::grpc::ServerReader< $Request$>* reader, "
- "$Response$* response) final override {\n"
+ "::grpc::ServerContext* /*context*/, "
+ "::grpc::ServerReader< $Request$>* /*reader*/, "
+ "$Response$* /*response*/) final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
"}\n");
@@ -689,8 +675,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "::grpc::ServerWriter< $Response$>* writer) final override "
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
"{\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
@@ -712,8 +698,8 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, "
- "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+ "::grpc::ServerContext* /*context*/, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
"final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
@@ -734,7 +720,7 @@ void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
printer->Print(*vars, "};\n");
}
-void PrintHeaderServerMethodStreamedUnary(
+static void PrintHeaderServerMethodStreamedUnary(
grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -747,7 +733,7 @@ void PrintHeaderServerMethodStreamedUnary(
"public BaseClass {\n");
printer->Print(
" private:\n"
- " void BaseClassMustBeDerivedFromService(const Service *service) "
+ " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
"{}\n");
printer->Print(" public:\n");
printer->Indent();
@@ -768,8 +754,8 @@ void PrintHeaderServerMethodStreamedUnary(
*vars,
"// disable regular version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "$Response$* response) final override {\n"
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "$Response$* /*response*/) final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
"}\n");
@@ -785,7 +771,7 @@ void PrintHeaderServerMethodStreamedUnary(
}
}
-void PrintHeaderServerMethodSplitStreaming(
+static void PrintHeaderServerMethodSplitStreaming(
grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -798,8 +784,8 @@ void PrintHeaderServerMethodSplitStreaming(
"public BaseClass {\n");
printer->Print(
" private:\n"
- " void BaseClassMustBeDerivedFromService(const Service *service) "
- "{}\n");
+ " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
+ "{ }\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(
@@ -820,8 +806,8 @@ void PrintHeaderServerMethodSplitStreaming(
*vars,
"// disable regular version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "::grpc::ServerWriter< $Response$>* writer) final override "
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
"{\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
@@ -838,7 +824,7 @@ void PrintHeaderServerMethodSplitStreaming(
}
}
-void PrintHeaderServerMethodGeneric(
+static void PrintHeaderServerMethodGeneric(
grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -849,7 +835,8 @@ void PrintHeaderServerMethodGeneric(
"class WithGenericMethod_$Method$ : public BaseClass {\n");
printer->Print(
" private:\n"
- " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
+ "{}\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(*vars,
@@ -865,8 +852,8 @@ void PrintHeaderServerMethodGeneric(
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "$Response$* response) final override {\n"
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "$Response$* /*response*/) final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
"}\n");
@@ -875,9 +862,9 @@ void PrintHeaderServerMethodGeneric(
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, "
- "::grpc::ServerReader< $Request$>* reader, "
- "$Response$* response) final override {\n"
+ "::grpc::ServerContext* /*context*/, "
+ "::grpc::ServerReader< $Request$>* /*reader*/, "
+ "$Response$* /*response*/) final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
"}\n");
@@ -886,8 +873,8 @@ void PrintHeaderServerMethodGeneric(
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, const $Request$* request, "
- "::grpc::ServerWriter< $Response$>* writer) final override "
+ "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
+ "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
"{\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
@@ -897,8 +884,8 @@ void PrintHeaderServerMethodGeneric(
*vars,
"// disable synchronous version of this method\n"
"::grpc::Status $Method$("
- "::grpc::ServerContext* context, "
- "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+ "::grpc::ServerContext* /*context*/, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
"final override {\n"
" abort();\n"
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
@@ -908,7 +895,7 @@ void PrintHeaderServerMethodGeneric(
printer->Print(*vars, "};\n");
}
-void PrintHeaderService(grpc_generator::Printer *printer,
+static void PrintHeaderService(grpc_generator::Printer *printer,
const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@@ -1001,9 +988,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print(*vars, "WithAsyncMethod_$method_name$<");
}
printer->Print("Service");
- for (int i = 0; i < service->method_count(); ++i) {
- printer->Print(" >");
- }
+ for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
printer->Print(" AsyncService;\n");
// Server side - Generic
@@ -1028,9 +1013,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
}
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
- if (service->method(i)->NoStreaming()) {
- printer->Print(" >");
- }
+ if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
}
printer->Print(" StreamedUnaryService;\n");
@@ -1052,9 +1035,7 @@ void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print("Service");
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
- if (ServerOnlyStreaming(method.get())) {
- printer->Print(" >");
- }
+ if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
}
printer->Print(" SplitStreamedService;\n");
@@ -1085,6 +1066,8 @@ void PrintHeaderService(grpc_generator::Printer *printer,
printer->Print(service->GetTrailingComments("//").c_str());
}
+} // namespace
+
grpc::string GetHeaderServices(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
@@ -1095,9 +1078,7 @@ grpc::string GetHeaderServices(grpc_generator::File *file,
// 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 (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;
@@ -1146,7 +1127,7 @@ grpc::string GetHeaderEpilogue(grpc_generator::File *file,
}
grpc::string GetSourcePrologue(grpc_generator::File *file,
- const Parameters & /*params*/) {
+ const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -1155,7 +1136,7 @@ grpc::string GetSourcePrologue(grpc_generator::File *file,
vars["filename"] = file->filename();
vars["filename_base"] = file->filename_without_ext();
- vars["message_header_ext"] = message_header_ext();
+ vars["message_header_ext"] = params.message_header_extension;
vars["service_header_ext"] = service_header_ext();
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
@@ -1179,14 +1160,15 @@ grpc::string GetSourceIncludes(grpc_generator::File *file,
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"};
+ "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);
@@ -1204,7 +1186,10 @@ grpc::string GetSourceIncludes(grpc_generator::File *file,
return output;
}
-void PrintSourceClientMethod(grpc_generator::Printer *printer,
+
+namespace {
+
+static void PrintSourceClientMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -1215,8 +1200,8 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
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"}};
+ } async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" },
+ { "PrepareAsync", "false", "", ", nullptr" } };
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::Status $ns$$Service$::Stub::$Method$("
@@ -1226,8 +1211,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
" 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];
+ 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,
@@ -1257,8 +1243,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"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];
+ 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;
@@ -1289,8 +1276,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"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];
+ 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;
@@ -1321,8 +1309,9 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
"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];
+ 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;
@@ -1344,20 +1333,18 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
}
}
-void PrintSourceServerMethod(grpc_generator::Printer *printer,
+static 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(
+ *vars,
+ "::grpc::Status $ns$$Service$::Service::$Method$("
+ "::grpc::ServerContext* /*context*/, "
+ "const $Request$* /*request*/, $Response$* /*response*/) {\n");
printer->Print(
" return ::grpc::Status("
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
@@ -1365,12 +1352,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
} 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");
+ "::grpc::ServerContext* /*context*/, "
+ "::grpc::ServerReader< $Request$>* /*reader*/, "
+ "$Response$* /*response*/) {\n");
printer->Print(
" return ::grpc::Status("
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
@@ -1378,12 +1362,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
} 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");
+ "::grpc::ServerContext* /*context*/, "
+ "const $Request$* /*request*/, "
+ "::grpc::ServerWriter< $Response$>* /*writer*/) {\n");
printer->Print(
" return ::grpc::Status("
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
@@ -1391,11 +1372,9 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
} else if (method->BidiStreaming()) {
printer->Print(*vars,
"::grpc::Status $ns$$Service$::Service::$Method$("
- "::grpc::ServerContext* context, "
+ "::grpc::ServerContext* /*context*/, "
"::grpc::ServerReaderWriter< $Response$, $Request$>* "
- "stream) {\n");
- printer->Print(" (void) context;\n");
- printer->Print(" (void) stream;\n");
+ "/*stream*/) {\n");
printer->Print(
" return ::grpc::Status("
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
@@ -1403,7 +1382,7 @@ void PrintSourceServerMethod(grpc_generator::Printer *printer,
}
}
-void PrintSourceService(grpc_generator::Printer *printer,
+static void PrintSourceService(grpc_generator::Printer *printer,
const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@@ -1421,7 +1400,7 @@ void PrintSourceService(grpc_generator::Printer *printer,
printer->Print(*vars,
"std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
"const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
- "const ::grpc::StubOptions& options) {\n"
+ "const ::grpc::StubOptions& /*options*/) {\n"
" std::unique_ptr< $ns$$Service$::Stub> stub(new "
"$ns$$Service$::Stub(channel));\n"
" return stub;\n"
@@ -1520,6 +1499,8 @@ void PrintSourceService(grpc_generator::Printer *printer,
}
}
+} // namespace
+
grpc::string GetSourceServices(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
@@ -1530,9 +1511,7 @@ grpc::string GetSourceServices(grpc_generator::File *file,
// 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 (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["ns"] = params.services_namespace + "::";
vars["prefix"] = params.services_namespace;
@@ -1567,9 +1546,8 @@ grpc::string GetSourceEpilogue(grpc_generator::File *file,
return temp;
}
-// TODO(mmukhi): Make sure we need parameters or not.
grpc::string GetMockPrologue(grpc_generator::File *file,
- const Parameters & /*params*/) {
+ const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -1578,7 +1556,7 @@ grpc::string GetMockPrologue(grpc_generator::File *file,
vars["filename"] = file->filename();
vars["filename_base"] = file->filename_without_ext();
- vars["message_header_ext"] = message_header_ext();
+ vars["message_header_ext"] = params.message_header_extension;
vars["service_header_ext"] = service_header_ext();
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
@@ -1604,9 +1582,9 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
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",
+ "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);
@@ -1625,7 +1603,10 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
return output;
}
-void PrintMockClientMethods(grpc_generator::Printer *printer,
+
+namespace {
+
+static void PrintMockClientMethods(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
@@ -1636,15 +1617,17 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
grpc::string prefix;
grpc::string method_params; // extra arguments to method
int extra_method_param_count;
- } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
+ } 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];
+ 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,
@@ -1659,12 +1642,13 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"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];
+ 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);
+ flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
printer->Print(*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncWriterInterface< $Request$>*"
@@ -1677,8 +1661,9 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"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];
+ 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"] =
@@ -1696,8 +1681,9 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
"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];
+ 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"] =
@@ -1712,7 +1698,7 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
}
}
-void PrintMockService(grpc_generator::Printer *printer,
+static void PrintMockService(grpc_generator::Printer *printer,
const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@@ -1728,6 +1714,8 @@ void PrintMockService(grpc_generator::Printer *printer,
printer->Print("};\n");
}
+} // namespace
+
grpc::string GetMockServices(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
@@ -1738,9 +1726,7 @@ grpc::string GetMockServices(grpc_generator::File *file,
// 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 (!file->package().empty()) { vars["Package"].append("."); }
if (!params.services_namespace.empty()) {
vars["services_namespace"] = params.services_namespace;
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h
index 6119ebe289..a9af1a6794 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h
@@ -1,36 +1,3 @@
-/*
- *
- * 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
@@ -41,12 +8,11 @@
#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
+# include <string>
+# define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
@@ -67,6 +33,8 @@ struct Parameters {
grpc::string grpc_search_path;
// Generate GMOCK code to facilitate unit testing.
bool generate_mock_code;
+ // By default, use "_generated.h"
+ std::string message_header_extension;
};
// Return the prologue of the generated header file.
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
index d646451aa6..ad4694b107 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
@@ -1,47 +1,13 @@
-/*
- *
- * 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 "src/compiler/go_generator.h"
-#include <map>
#include <cctype>
+#include <map>
#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();
+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) {
@@ -53,24 +19,23 @@ inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
}
namespace grpc_go_generator {
+namespace {
// 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;
+static 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;
+static 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,
+static 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");
@@ -82,50 +47,65 @@ void GenerateError(grpc_generator::Printer *printer,
}
// Generates imports for the service
-void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
+static 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");
+ 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(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");
+ printer->Outdent();
+ printer->Print(")\n\n");
}
// Generates Server method signature source
-void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
+static 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$");
- }
+ 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,
+static 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["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");
@@ -133,258 +113,281 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
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->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");
+ 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");
+ 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");
- }
-
+ 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,
+static 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$");
+ 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,
+static 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) ");
+ 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");
+ 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");
+ 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)) {
+ 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");
+ }
+ 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();
+ 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");
+ 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");
- }
+ 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,
+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["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();
+ 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);
- }
+ 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->Outdent();
+ printer->Print("}\n\n");
printer->Print(vars, "type Unimplemented$Service$Server struct {\n");
printer->Print("}\n\n");
@@ -397,13 +400,17 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
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->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(vars,
+ "func (Unimplemented$Service$Server) "
+ "mustEmbedUnimplemented$Service$Server() {}");
printer->Print("\n\n");
printer->Print(vars, "type Unsafe$Service$Server interface {\n");
@@ -411,91 +418,90 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
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");
+ // 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");
+}
+} // namespace
// 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');
+ 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;
+ 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
+} // 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
index baa94e0599..766e100c58 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h
@@ -1,40 +1,8 @@
-/*
- *
- * 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
+// go generator is used to generate GRPC code for serialization system, such as
+// flatbuffers
#include <memory>
#include <vector>
@@ -43,14 +11,15 @@
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
+ // 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
+ // Package name for the service
grpc::string package_name;
- //Prefix for RPC Calls
+ // Prefix for RPC Calls
grpc::string service_prefix;
};
@@ -59,6 +28,6 @@ grpc::string GenerateServiceSource(grpc_generator::File *file,
const grpc_generator::Service *service,
grpc_go_generator::Parameters *parameters);
-}
+} // namespace grpc_go_generator
#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
index d2cf5ccc14..bfe2b111db 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
@@ -23,21 +23,18 @@
#include <utility>
#include <vector>
-// just to get flatbuffer_version_string()
-#include <flatbuffers/flatbuffers.h>
-#include <flatbuffers/util.h>
+#include "flatbuffers/util.h"
#define to_string flatbuffers::NumToString
// Stringify helpers used solely to cast GRPC_VERSION
#ifndef STR
-#define STR(s) #s
+# define STR(s) # s
#endif
#ifndef XSTR
-#define XSTR(s) STR(s)
+# define XSTR(s) STR(s)
#endif
-
typedef grpc_generator::Printer Printer;
typedef std::map<grpc::string, grpc::string> VARS;
typedef grpc_generator::Service ServiceDescriptor;
@@ -47,13 +44,13 @@ typedef grpc_generator::Method MethodDescriptor;
namespace grpc_java_generator {
typedef std::string string;
+namespace {
// Generates imports for the service
-void GenerateImports(grpc_generator::File* file,
- grpc_generator::Printer* printer, VARS& vars) {
+static 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(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");
@@ -67,7 +64,7 @@ void GenerateImports(grpc_generator::File* file,
// 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) {
+static string MixedLower(const string &word) {
string w;
w += static_cast<string::value_type>(tolower(word[0]));
bool after_underscore = false;
@@ -87,7 +84,7 @@ static string MixedLower(const string& word) {
// - 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) {
+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]));
@@ -98,47 +95,47 @@ static string ToAllUpperCase(const string& word) {
return w;
}
-static inline string LowerMethodName(const MethodDescriptor* method) {
+static inline string LowerMethodName(const MethodDescriptor *method) {
return MixedLower(method->name());
}
-static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
+static inline string MethodPropertiesFieldName(const MethodDescriptor *method) {
return "METHOD_" + ToAllUpperCase(method->name());
}
static inline string MethodPropertiesGetterName(
- const MethodDescriptor* method) {
+ const MethodDescriptor *method) {
return MixedLower("get_" + method->name() + "_method");
}
-static inline string MethodIdFieldName(const MethodDescriptor* method) {
+static inline string MethodIdFieldName(const MethodDescriptor *method) {
return "METHODID_" + ToAllUpperCase(method->name());
}
-static inline string JavaClassName(VARS& vars, const string& 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) {
+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) {
+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();
+ const char *p = full.data();
+ const char *end = p + full.size();
while (p != end) {
if (*p == c) {
++p;
} else {
- const char* start = p;
+ const char *start = p;
while (++p != end && *p != c)
;
*result++ = string(start, p - start);
@@ -160,13 +157,13 @@ static void GrpcSplitStringToIteratorUsing(const string& full,
}
}
-static void GrpcSplitStringUsing(const string& full, const char* delim,
- std::vector<string>* result) {
+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) {
+static std::vector<string> GrpcSplit(const string &full, const char *delim) {
std::vector<string> result;
GrpcSplitStringUsing(full, delim, &result);
return result;
@@ -174,7 +171,7 @@ static std::vector<string> GrpcSplit(const string& full, const char* delim) {
// TODO(nmittler): Remove once protobuf includes javadoc methods in
// distribution.
-static string GrpcEscapeJavadoc(const string& input) {
+static string GrpcEscapeJavadoc(const string &input) {
string result;
result.reserve(input.size() * 2);
@@ -221,9 +218,7 @@ static string GrpcEscapeJavadoc(const string& input) {
// Java interprets Unicode escape sequences anywhere!
result.append("&#92;");
break;
- default:
- result.push_back(c);
- break;
+ default: result.push_back(c); break;
}
prev = c;
@@ -232,7 +227,7 @@ static string GrpcEscapeJavadoc(const string& input) {
return result;
}
-static std::vector<string> GrpcGetDocLines(const string& comments) {
+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
@@ -243,27 +238,23 @@ static std::vector<string> GrpcGetDocLines(const string& comments) {
string escapedComments = GrpcEscapeJavadoc(comments);
std::vector<string> lines = GrpcSplit(escapedComments, "\n");
- while (!lines.empty() && lines.back().empty()) {
- lines.pop_back();
- }
+ while (!lines.empty() && lines.back().empty()) { lines.pop_back(); }
return lines;
}
return std::vector<string>();
}
static std::vector<string> GrpcGetDocLinesForDescriptor(
- const DescriptorType* descriptor) {
+ const DescriptorType *descriptor) {
return descriptor->GetAllComments();
// return GrpcGetDocLines(descriptor->GetLeadingComments("///"));
}
-static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
- const std::vector<string>& lines,
+static void GrpcWriteDocCommentBody(Printer *printer, VARS &vars,
+ const std::vector<string> &lines,
bool surroundWithPreTag) {
if (!lines.empty()) {
- if (surroundWithPreTag) {
- printer->Print(" * <pre>\n");
- }
+ 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
@@ -277,73 +268,72 @@ static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
}
}
- if (surroundWithPreTag) {
- printer->Print(" * </pre>\n");
- }
+ if (surroundWithPreTag) { printer->Print(" * </pre>\n"); }
}
}
-static void GrpcWriteDocComment(Printer* printer, VARS& vars,
- const string& comments) {
+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) {
+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) {
+static 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");
+// 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) {
+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
+ // 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_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();
@@ -353,8 +343,10 @@ static void PrintMethodFields(Printer* p, VARS& vars,
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();
+ 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";
@@ -394,32 +386,32 @@ static void PrintMethodFields(Printer* p, VARS& 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,
+ "@$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";
@@ -451,11 +443,11 @@ enum StubType {
enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 };
-static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
- const ServiceDescriptor* service);
+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,
+static void PrintStub(Printer *p, VARS &vars, const ServiceDescriptor *service,
StubType type) {
const string service_name = service->name();
vars["service_name"] = service_name;
@@ -476,7 +468,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
break;
case BLOCKING_CLIENT_INTERFACE:
interface = true;
- FLATBUFFERS_FALLTHROUGH(); // fall thru
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
case BLOCKING_CLIENT_IMPL:
call_type = BLOCKING_CALL;
stub_name += "BlockingStub";
@@ -484,7 +476,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
break;
case FUTURE_CLIENT_INTERFACE:
interface = true;
- FLATBUFFERS_FALLTHROUGH(); // fall thru
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
case FUTURE_CLIENT_IMPL:
call_type = FUTURE_CALL;
stub_name += "FutureStub";
@@ -501,9 +493,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
vars["client_name"] = client_name;
// Class head
- if (!interface) {
- GrpcWriteServiceDocComment(p, vars, service);
- }
+ if (!interface) { GrpcWriteServiceDocComment(p, vars, service); }
if (impl_base) {
p->Print(vars,
"public static abstract class $abstract_name$ implements "
@@ -546,8 +536,10 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
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();
+ 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
@@ -563,9 +555,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
p->Print("\n");
// TODO(nmittler): Replace with WriteMethodDocComment once included by the
// protobuf distro.
- if (!interface) {
- GrpcWriteMethodDocComment(p, vars, &*method);
- }
+ if (!interface) { GrpcWriteMethodDocComment(p, vars, &*method); }
p->Print("public ");
switch (call_type) {
case BLOCKING_CALL:
@@ -630,8 +620,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
"responseObserver);\n");
}
break;
- default:
- break;
+ default: break;
}
} else if (!interface) {
switch (call_type) {
@@ -706,15 +695,15 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
}
static bool CompareMethodClientStreaming(
- const std::unique_ptr<const grpc_generator::Method>& method1,
- const std::unique_ptr<const grpc_generator::Method>& method2) {
+ 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) {
+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());
@@ -724,7 +713,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
stable_sort(sorted_methods.begin(), sorted_methods.end(),
CompareMethodClientStreaming);
for (size_t i = 0; i < sorted_methods.size(); i++) {
- auto& method = sorted_methods[i];
+ auto &method = sorted_methods[i];
vars["method_id"] = to_string(i);
vars["method_id_name"] = MethodIdFieldName(&*method);
p->Print(vars,
@@ -757,9 +746,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
- if (method->ClientStreaming() || method->BidiStreaming()) {
- continue;
- }
+ 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());
@@ -791,9 +778,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
- if (!(method->ClientStreaming() || method->BidiStreaming())) {
- continue;
- }
+ 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());
@@ -818,8 +803,8 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
p->Print("}\n\n");
}
-static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
- const ServiceDescriptor* service) {
+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"] =
@@ -911,8 +896,8 @@ static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
p->Print("}\n");
}
-static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
- const ServiceDescriptor* service) {
+static void PrintBindServiceMethodBody(Printer *p, VARS &vars,
+ const ServiceDescriptor *service) {
vars["service_name"] = service->name();
p->Indent();
p->Print(vars,
@@ -927,8 +912,10 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
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();
+ bool client_streaming =
+ method->ClientStreaming() || method->BidiStreaming();
+ bool server_streaming =
+ method->ServerStreaming() || method->BidiStreaming();
if (client_streaming) {
if (server_streaming) {
vars["calls_method"] = "asyncBidiStreamingCall";
@@ -962,8 +949,8 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
p->Outdent();
}
-static void PrintService(Printer* p, VARS& vars,
- const ServiceDescriptor* service,
+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());
@@ -1043,7 +1030,7 @@ static void PrintService(Printer* p, VARS& vars,
p->Print("}\n");
}
-void PrintStaticImports(Printer* p) {
+static void PrintStaticImports(Printer *p) {
p->Print(
"import java.nio.ByteBuffer;\n"
"import static "
@@ -1076,8 +1063,8 @@ void PrintStaticImports(Printer* p) {
"io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n");
}
-void GenerateService(const grpc_generator::Service* service,
- grpc_generator::Printer* printer, VARS& vars,
+static 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.
@@ -1111,10 +1098,11 @@ void GenerateService(const grpc_generator::Service* service,
PrintService(printer, vars, service, disable_version);
}
+} // namespace
grpc::string GenerateServiceSource(
- grpc_generator::File* file, const grpc_generator::Service* service,
- grpc_java_generator::Parameters* parameters) {
+ grpc_generator::File *file, const grpc_generator::Service *service,
+ grpc_java_generator::Parameters *parameters) {
grpc::string out;
auto printer = file->CreatePrinter(&out);
VARS vars;
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
index 8108db45d5..d5f69e20e7 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
@@ -23,8 +23,9 @@
#include "src/compiler/python_generator.h"
namespace grpc_python_generator {
+namespace {
-grpc::string GenerateMethodType(const grpc_generator::Method *method) {
+static grpc::string GenerateMethodType(const grpc_generator::Method *method) {
if (method->NoStreaming())
return "unary_unary";
@@ -131,6 +132,7 @@ void GenerateRegister(const grpc_generator::Service *service,
printer->Outdent();
printer->Print("\n");
}
+} // namespace
grpc::string Generate(grpc_generator::File *file,
const grpc_generator::Service *service) {
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h
index 4f8f5cc806..40d29aada5 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h
@@ -21,7 +21,6 @@
#include <utility>
-#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
namespace grpc_python_generator {
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h
index 0449498198..f89288d756 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h
@@ -19,11 +19,10 @@
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+#include <map>
#include <memory>
#include <vector>
-#include "src/compiler/config.h"
-
#ifndef GRPC_CUSTOM_STRING
# include <string>
# define GRPC_CUSTOM_STRING std::string
@@ -93,7 +92,7 @@ struct 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 SetIndentationSize(const size_t size) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
index 403a803ef1..b0a96d869a 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
@@ -28,8 +28,9 @@
#include "src/compiler/swift_generator.h"
namespace grpc_swift_generator {
+namespace {
-std::string WrapInNameSpace(const std::vector<std::string> &components,
+static 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)
@@ -37,14 +38,14 @@ std::string WrapInNameSpace(const std::vector<std::string> &components,
return qualified_name + name;
}
-grpc::string GenerateMessage(const std::vector<std::string> &components,
+static 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,
+static void GenerateClientFuncName(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -82,7 +83,7 @@ void GenerateClientFuncName(const grpc_generator::Method *method,
" ) -> BidirectionalStreamingCall<$Input$, $Output$>");
}
-void GenerateClientFuncBody(const grpc_generator::Method *method,
+static void GenerateClientFuncBody(const grpc_generator::Method *method,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -372,6 +373,7 @@ void GenerateServerProtocol(const grpc_generator::Service *service,
}
printer->Print("}");
}
+} // namespace
grpc::string Generate(grpc_generator::File *file,
const grpc_generator::Service *service) {
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h
index 1639cb07c8..2a226fa940 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h
@@ -1,40 +1,22 @@
/*
+ * Copyright 2020 Google Inc. All rights reserved.
*
- * 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
*
- * 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.
+ * 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 <memory>
#include <vector>
-#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
index e49fd8d925..ff362b774a 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
@@ -21,50 +21,42 @@
* be maintained according to the Swift-grpc repository
*/
+#include "src/compiler/ts_generator.h"
+
#include <map>
#include <sstream>
#include "flatbuffers/util.h"
#include "src/compiler/schema_interface.h"
-#include "src/compiler/ts_generator.h"
namespace grpc_ts_generator {
+namespace {
-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,
+static grpc::string GenerateNamespace(const std::vector<std::string> ns,
const std::string filename,
const bool include_separator) {
grpc::string path = "";
if (include_separator) path += ".";
- for (auto it = namepsace.begin(); it < namepsace.end(); it++) {
+ for (auto it = ns.begin(); it < ns.end(); it++) {
if (include_separator) path += "/";
- path += include_separator ? ToDasherizedCase(*it) : *it + "_";
+ path += include_separator
+ ? flatbuffers::ConvertCase(*it, flatbuffers::Case::kDasher,
+ flatbuffers::Case::kUpperCamel)
+ : *it + "_";
}
if (include_separator) path += "/";
- path += include_separator ? ToDasherizedCase(filename) : filename;
+ path += include_separator
+ ? flatbuffers::ConvertCase(filename, flatbuffers::Case::kDasher,
+ flatbuffers::Case::kUpperCamel)
+ : filename;
return path;
}
// MARK: - Shared code
-void GenerateImports(const grpc_generator::Service *service,
+static void GenerateImports(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary,
const bool grpc_var_import) {
@@ -105,15 +97,15 @@ void GenerateImports(const grpc_generator::Service *service,
}
printer->Print("\n");
if (grpc_var_import)
- printer->Print("var grpc = require('grpc');\n");
+ printer->Print("var grpc = require('@grpc/grpc-js');\n");
else
- printer->Print("import * as grpc from 'grpc';\n");
+ printer->Print("import * as grpc from '@grpc/grpc-js';\n");
printer->Print("\n");
}
// MARK: - Generate Main GRPC Code
-void GetStreamType(grpc_generator::Printer *printer,
+static void GetStreamType(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -125,7 +117,7 @@ void GetStreamType(grpc_generator::Printer *printer,
printer->Print(vars, "responseStream: $ServerStreaming$,\n");
}
-void GenerateSerializeMethod(grpc_generator::Printer *printer,
+static 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");
@@ -136,12 +128,12 @@ void GenerateSerializeMethod(grpc_generator::Printer *printer,
"throw new Error('Expected argument of type $VALUE$');\n");
printer->Outdent();
printer->Print("}\n");
- printer->Print(vars, "return buffer_args.serialize();\n");
+ printer->Print(vars, "return Buffer.from(buffer_args.serialize());\n");
printer->Outdent();
printer->Print("}\n\n");
}
-void GenerateDeserializeMethod(
+static void GenerateDeserializeMethod(
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -154,7 +146,7 @@ void GenerateDeserializeMethod(
printer->Print("}\n\n");
}
-void GenerateMethods(const grpc_generator::Service *service,
+static void GenerateMethods(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -186,7 +178,7 @@ void GenerateMethods(const grpc_generator::Service *service,
}
}
-void GenerateService(const grpc_generator::Service *service,
+static void GenerateService(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -221,6 +213,8 @@ void GenerateService(const grpc_generator::Service *service,
"grpc.makeGenericClientConstructor($NAME$);");
}
+} // namespace
+
grpc::string Generate(grpc_generator::File *file,
const grpc_generator::Service *service,
const grpc::string &filename) {
@@ -242,9 +236,11 @@ grpc::string Generate(grpc_generator::File *file,
return output;
}
+namespace {
+
// MARK: - Generate Interface
-void FillInterface(grpc_generator::Printer *printer,
+static void FillInterface(grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
printer->Print(vars,
@@ -262,7 +258,7 @@ void FillInterface(grpc_generator::Printer *printer,
printer->Print("}\n");
}
-void GenerateInterfaces(const grpc_generator::Service *service,
+static void GenerateInterfaces(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -284,11 +280,13 @@ void GenerateInterfaces(const grpc_generator::Service *service,
}
}
-void GenerateExportedInterface(
+static 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->Print(vars,
+ "export interface I$ServiceName$Server extends "
+ "grpc.UntypedServiceImplementation {\n");
printer->Indent();
for (auto it = 0; it < service->method_count(); it++) {
auto method = service->method(it);
@@ -326,7 +324,7 @@ void GenerateExportedInterface(
printer->Print("}\n");
}
-void GenerateMainInterface(const grpc_generator::Service *service,
+static void GenerateMainInterface(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -351,11 +349,11 @@ void GenerateMainInterface(const grpc_generator::Service *service,
GenerateExportedInterface(service, printer, &vars);
}
-grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; }
+static grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; }
-grpc::string GenerateOptions() { return "options: Partial<grpc.CallOptions>"; }
+static grpc::string GenerateOptions() { return "options: Partial<grpc.CallOptions>"; }
-void GenerateUnaryClientInterface(
+static void GenerateUnaryClientInterface(
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -370,7 +368,7 @@ void GenerateUnaryClientInterface(
printer->Print(vars, (main + meta_data + options + callback).c_str());
}
-void GenerateClientWriteStreamInterface(
+static void GenerateClientWriteStreamInterface(
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -387,7 +385,7 @@ void GenerateClientWriteStreamInterface(
printer->Print(vars, (main + meta_data + options + callback).c_str());
}
-void GenerateClientReadableStreamInterface(
+static void GenerateClientReadableStreamInterface(
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -399,7 +397,7 @@ void GenerateClientReadableStreamInterface(
printer->Print(vars, (main + options + end_function).c_str());
}
-void GenerateDepluxStreamInterface(
+static void GenerateDepluxStreamInterface(
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -415,7 +413,7 @@ void GenerateDepluxStreamInterface(
.c_str());
}
-void GenerateClientInterface(const grpc_generator::Service *service,
+static void GenerateClientInterface(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -453,7 +451,7 @@ void GenerateClientInterface(const grpc_generator::Service *service,
printer->Print("}\n");
}
-void GenerateClientClassInterface(
+static void GenerateClientClassInterface(
const grpc_generator::Service *service, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
@@ -463,7 +461,7 @@ void GenerateClientClassInterface(
printer->Indent();
printer->Print(
"constructor(address: string, credentials: grpc.ChannelCredentials, "
- "options?: object);");
+ "options?: object);\n");
for (auto it = 0; it < service->method_count(); it++) {
auto method = service->method(it);
vars["MethodName"] = method->name();
@@ -494,6 +492,8 @@ void GenerateClientClassInterface(
printer->Outdent();
printer->Print("}\n");
}
+} // namespace
+
grpc::string GenerateInterface(grpc_generator::File *file,
const grpc_generator::Service *service,
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h
index a33bb3c5d2..a356659daa 100644
--- a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h
@@ -1,41 +1,7 @@
-/*
- *
- * 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 <vector>
-#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING
@@ -58,4 +24,3 @@ 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/allocator.h b/contrib/libs/flatbuffers/include/flatbuffers/allocator.h
new file mode 100644
index 0000000000..7f4d614f25
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/allocator.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 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_ALLOCATOR_H_
+#define FLATBUFFERS_ALLOCATOR_H_
+
+#include "base.h"
+
+namespace flatbuffers {
+
+// Allocator interface. This is flatbuffers-specific and meant only for
+// `vector_downward` usage.
+class Allocator {
+ public:
+ virtual ~Allocator() {}
+
+ // Allocate `size` bytes of memory.
+ virtual uint8_t *allocate(size_t size) = 0;
+
+ // Deallocate `size` bytes of memory at `p` allocated by this allocator.
+ virtual void deallocate(uint8_t *p, size_t size) = 0;
+
+ // Reallocate `new_size` bytes of memory, replacing the old region of size
+ // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
+ // and is intended specifcally for `vector_downward` use.
+ // `in_use_back` and `in_use_front` indicate how much of `old_size` is
+ // actually in use at each end, and needs to be copied.
+ virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
+ size_t new_size, size_t in_use_back,
+ size_t in_use_front) {
+ FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
+ uint8_t *new_p = allocate(new_size);
+ memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
+ in_use_front);
+ deallocate(old_p, old_size);
+ return new_p;
+ }
+
+ protected:
+ // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
+ // to `new_p` of `new_size`. Only memory of size `in_use_front` and
+ // `in_use_back` will be copied from the front and back of the old memory
+ // allocation.
+ void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
+ size_t new_size, size_t in_use_back,
+ size_t in_use_front) {
+ memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
+ in_use_back);
+ memcpy(new_p, old_p, in_use_front);
+ }
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_ALLOCATOR_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/array.h b/contrib/libs/flatbuffers/include/flatbuffers/array.h
new file mode 100644
index 0000000000..4a52ed1dae
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/array.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2021 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_ARRAY_H_
+#define FLATBUFFERS_ARRAY_H_
+
+#include <cstdint>
+#include <memory>
+
+#include "base.h"
+#include "stl_emulation.h"
+#include "vector.h"
+
+namespace flatbuffers {
+
+// This is used as a helper type for accessing arrays.
+template<typename T, uint16_t length> class Array {
+ // Array<T> can carry only POD data types (scalars or structs).
+ typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
+ scalar_tag;
+ typedef
+ typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
+ IndirectHelperType;
+
+ public:
+ typedef uint16_t size_type;
+ typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
+ typedef VectorConstIterator<T, return_type, uoffset_t> const_iterator;
+ typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+ // If T is a LE-scalar or a struct (!scalar_tag::value).
+ static FLATBUFFERS_CONSTEXPR bool is_span_observable =
+ (scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1)) ||
+ !scalar_tag::value;
+
+ FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
+
+ return_type Get(uoffset_t i) const {
+ FLATBUFFERS_ASSERT(i < size());
+ return IndirectHelper<IndirectHelperType>::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_iterator begin() const { return const_iterator(Data(), 0); }
+ const_iterator end() const { return const_iterator(Data(), size()); }
+
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
+ const_iterator cbegin() const { return begin(); }
+ const_iterator cend() const { return end(); }
+
+ const_reverse_iterator crbegin() const { return rbegin(); }
+ const_reverse_iterator crend() const { return rend(); }
+
+ // Get a mutable pointer to elements inside this array.
+ // This method used to mutate arrays of structs followed by a @p Mutate
+ // operation. For primitive types use @p Mutate directly.
+ // @warning Assignments and reads to/from the dereferenced pointer are not
+ // automatically converted to the correct endianness.
+ typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
+ GetMutablePointer(uoffset_t i) const {
+ FLATBUFFERS_ASSERT(i < size());
+ return const_cast<T *>(&data()[i]);
+ }
+
+ // Change elements if you have a non-const pointer to this object.
+ void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
+
+ // The raw data in little endian format. Use with care.
+ const uint8_t *Data() const { return data_; }
+
+ uint8_t *Data() { return data_; }
+
+ // Similarly, but typed, much like std::vector::data
+ const T *data() const { return reinterpret_cast<const T *>(Data()); }
+ T *data() { return reinterpret_cast<T *>(Data()); }
+
+ // Copy data from a span with endian conversion.
+ // If this Array and the span overlap, the behavior is undefined.
+ void CopyFromSpan(flatbuffers::span<const T, length> src) {
+ const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
+ const auto p2 = Data();
+ FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
+ !(p2 >= p1 && p2 < (p1 + length)));
+ (void)p1;
+ (void)p2;
+ CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
+ }
+
+ protected:
+ void MutateImpl(flatbuffers::true_type, uoffset_t i, const T &val) {
+ FLATBUFFERS_ASSERT(i < size());
+ WriteScalar(data() + i, val);
+ }
+
+ void MutateImpl(flatbuffers::false_type, uoffset_t i, const T &val) {
+ *(GetMutablePointer(i)) = val;
+ }
+
+ void CopyFromSpanImpl(flatbuffers::true_type,
+ flatbuffers::span<const T, length> src) {
+ // Use std::memcpy() instead of std::copy() to avoid performance degradation
+ // due to aliasing if T is char or unsigned char.
+ // The size is known at compile time, so memcpy would be inlined.
+ std::memcpy(data(), src.data(), length * sizeof(T));
+ }
+
+ // Copy data from flatbuffers::span with endian conversion.
+ void CopyFromSpanImpl(flatbuffers::false_type,
+ flatbuffers::span<const T, length> src) {
+ for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
+ }
+
+ // This class is only used to access pre-existing data. Don't ever
+ // try to construct these manually.
+ // 'constexpr' allows us to use 'size()' at compile time.
+ // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
+ // a constructor.
+#if defined(__cpp_constexpr)
+ constexpr Array();
+#else
+ Array();
+#endif
+
+ uint8_t data_[length * sizeof(T)];
+
+ private:
+ // This class is a pointer. Copying will therefore create an invalid object.
+ // Private and unimplemented copy constructor.
+ Array(const Array &);
+ Array &operator=(const Array &);
+};
+
+// Specialization for Array[struct] with access using Offset<void> pointer.
+// This specialization used by idl_gen_text.cpp.
+template<typename T, uint16_t length, template<typename> class OffsetT>
+class Array<OffsetT<T>, length> {
+ static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
+
+ public:
+ typedef const void *return_type;
+ typedef uint16_t size_type;
+
+ const uint8_t *Data() const { return data_; }
+
+ // Make idl_gen_text.cpp::PrintContainer happy.
+ return_type operator[](uoffset_t) const {
+ FLATBUFFERS_ASSERT(false);
+ return nullptr;
+ }
+
+ private:
+ // This class is only used to access pre-existing data.
+ Array();
+ Array(const Array &);
+ Array &operator=(const Array &);
+
+ uint8_t data_[1];
+};
+
+template<class U, uint16_t N>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(Array<U, N> &arr)
+ FLATBUFFERS_NOEXCEPT {
+ static_assert(
+ Array<U, N>::is_span_observable,
+ "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
+ return span<U, N>(arr.data(), N);
+}
+
+template<class U, uint16_t N>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
+ const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
+ static_assert(
+ Array<U, N>::is_span_observable,
+ "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
+ return span<const U, N>(arr.data(), N);
+}
+
+template<class U, uint16_t N>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t, sizeof(U) * N>
+make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
+ static_assert(Array<U, N>::is_span_observable,
+ "internal error, Array<T> might hold only scalars or structs");
+ return span<uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
+}
+
+template<class U, uint16_t N>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t, sizeof(U) * N>
+make_bytes_span(const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
+ static_assert(Array<U, N>::is_span_observable,
+ "internal error, Array<T> might hold only scalars or structs");
+ return span<const uint8_t, sizeof(U) * N>(arr.Data(), sizeof(U) * N);
+}
+
+// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
+// without endian conversion. Use with care.
+// TODO: move these Cast-methods to `internal` namespace.
+template<typename T, uint16_t length>
+Array<T, length> &CastToArray(T (&arr)[length]) {
+ return *reinterpret_cast<Array<T, length> *>(arr);
+}
+
+template<typename T, uint16_t length>
+const Array<T, length> &CastToArray(const T (&arr)[length]) {
+ return *reinterpret_cast<const Array<T, length> *>(arr);
+}
+
+template<typename E, typename T, uint16_t length>
+Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
+ static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
+ return *reinterpret_cast<Array<E, length> *>(arr);
+}
+
+template<typename E, typename T, uint16_t length>
+const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {
+ static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
+ return *reinterpret_cast<const Array<E, length> *>(arr);
+}
+
+template<typename T, uint16_t length>
+bool operator==(const Array<T, length> &lhs,
+ const Array<T, length> &rhs) noexcept {
+ return std::addressof(lhs) == std::addressof(rhs) ||
+ (lhs.size() == rhs.size() &&
+ std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0);
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_ARRAY_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/base.h b/contrib/libs/flatbuffers/include/flatbuffers/base.h
index df6eea87df..9b6cc24b13 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/base.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/base.h
@@ -32,7 +32,7 @@
#include <cstdlib>
#include <cstring>
-#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
+#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__)
#error #include <utility.h>
#else
#include <utility>
@@ -43,6 +43,7 @@
#include <vector>
#include <set>
#include <algorithm>
+#include <limits>
#include <iterator>
#include <memory>
@@ -50,10 +51,6 @@
#include <unistd.h>
#endif
-#ifdef _STLPORT_VERSION
- #define FLATBUFFERS_CPP98_STL
-#endif
-
#ifdef __ANDROID__
#include <android/api-level.h>
#endif
@@ -142,9 +139,9 @@
#endif
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
-#define FLATBUFFERS_VERSION_MAJOR 2
-#define FLATBUFFERS_VERSION_MINOR 0
-#define FLATBUFFERS_VERSION_REVISION 0
+#define FLATBUFFERS_VERSION_MAJOR 23
+#define FLATBUFFERS_VERSION_MINOR 5
+#define FLATBUFFERS_VERSION_REVISION 9
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {
@@ -237,16 +234,26 @@ namespace flatbuffers {
}
#define FLATBUFFERS_HAS_STRING_VIEW 1
// Check for absl::string_view
- #elif __has_include("absl/strings/string_view.h")
- #error #include "absl/strings/string_view.h"
- namespace flatbuffers {
- typedef absl::string_view string_view;
- }
- #define FLATBUFFERS_HAS_STRING_VIEW 1
+ #elif __has_include("absl/strings/string_view.h") && \
+ __has_include("absl/base/config.h") && \
+ (__cplusplus >= 201411)
+ #include "absl/base/config.h"
+ #if !defined(ABSL_USES_STD_STRING_VIEW)
+ #error #include "absl/strings/string_view.h"
+ namespace flatbuffers {
+ typedef absl::string_view string_view;
+ }
+ #define FLATBUFFERS_HAS_STRING_VIEW 1
+ #endif
#endif
#endif // __has_include
#endif // !FLATBUFFERS_HAS_STRING_VIEW
+#ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
+ // Allow heap allocations to be used
+ #define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1
+#endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK
+
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
// Modern (C++11) strtod and strtof functions are available for use.
// 1) nan/inf strings as argument of strtod;
@@ -259,9 +266,12 @@ namespace flatbuffers {
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
- // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
- #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
- (defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21))))
+ // Enable locale independent functions {strtof_l, strtod_l,strtoll_l,
+ // strtoull_l}.
+ #if (defined(_MSC_VER) && _MSC_VER >= 1800) || \
+ (defined(__ANDROID_API__) && __ANDROID_API__>= 21) || \
+ (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
+ (!defined(__Fuchsia__) && !defined(__ANDROID_API__))
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
#else
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
@@ -269,14 +279,14 @@ namespace flatbuffers {
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
-// - __supress_ubsan__("undefined")
-// - __supress_ubsan__("signed-integer-overflow")
+// - __suppress_ubsan__("undefined")
+// - __suppress_ubsan__("signed-integer-overflow")
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
- #define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
+ #define __suppress_ubsan__(type) __attribute__((no_sanitize(type)))
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
- #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
+ #define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined))
#else
- #define __supress_ubsan__(type)
+ #define __suppress_ubsan__(type)
#endif
// This is constexpr function used for checking compile-time constants.
@@ -291,7 +301,7 @@ template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
#if ((__cplusplus >= 201703L) \
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
// All attributes unknown to an implementation are ignored without causing an error.
- #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
+ #define FLATBUFFERS_ATTRIBUTE(attr) attr
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
#else
@@ -316,9 +326,11 @@ namespace flatbuffers {
// Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems.
typedef uint32_t uoffset_t;
+typedef uint64_t uoffset64_t;
// Signed offsets for references that can go in both directions.
typedef int32_t soffset_t;
+typedef int64_t soffset64_t;
// Offset/index used in v-tables, can be changed to uint8_t in
// format forks to save a bit of space if desired.
@@ -327,10 +339,23 @@ typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
-#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(flatbuffers::soffset_t) * 8 - 1)) - 1)
+#define FLATBUFFERS_MAX_BUFFER_SIZE std::numeric_limits<flatbuffers::soffset_t>::max()
+#define FLATBUFFERS_MAX_64_BUFFER_SIZE std::numeric_limits<flatbuffers::soffset64_t>::max()
+
+// The minimum size buffer that can be a valid flatbuffer.
+// Includes the offset to the root table (uoffset_t), the offset to the vtable
+// of the root table (soffset_t), the size of the vtable (uint16_t), and the
+// size of the referring table (uint16_t).
+#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \
+ sizeof(uint16_t) + sizeof(uint16_t)
// We support aligning the contents of buffers up to this size.
-#define FLATBUFFERS_MAX_ALIGNMENT 16
+#ifndef FLATBUFFERS_MAX_ALIGNMENT
+ #define FLATBUFFERS_MAX_ALIGNMENT 32
+#endif
+
+/// @brief The length of a FlatBuffer file header.
+static const size_t kFileIdentifierLength = 4;
inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) {
return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) &&
@@ -399,7 +424,7 @@ template<typename T> T EndianScalar(T t) {
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
-__supress_ubsan__("alignment")
+__suppress_ubsan__("alignment")
T ReadScalar(const void *p) {
return EndianScalar(*reinterpret_cast<const T *>(p));
}
@@ -413,13 +438,13 @@ T ReadScalar(const void *p) {
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
-__supress_ubsan__("alignment")
+__suppress_ubsan__("alignment")
void WriteScalar(void *p, T t) {
*reinterpret_cast<T *>(p) = EndianScalar(t);
}
template<typename T> struct Offset;
-template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
+template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
}
@@ -430,10 +455,43 @@ template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Of
// Computes how many bytes you'd have to pad to be able to write an
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
// memory).
-__supress_ubsan__("unsigned-integer-overflow")
+__suppress_ubsan__("unsigned-integer-overflow")
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
return ((~buf_size) + 1) & (scalar_size - 1);
}
+// Generic 'operator==' with conditional specialisations.
+// T e - new value of a scalar field.
+// T def - default of scalar (is known at compile-time).
+template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
+
+#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
+ defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+// Like `operator==(e, def)` with weak NaN if T=(float|double).
+template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
+ return (e == def) || ((def != def) && (e != e));
+}
+template<> inline bool IsTheSameAs<float>(float e, float def) {
+ return IsFloatTheSameAs(e, def);
+}
+template<> inline bool IsTheSameAs<double>(double e, double def) {
+ return IsFloatTheSameAs(e, def);
+}
+#endif
+
+// Check 'v' is out of closed range [low; high].
+// Workaround for GCC warning [-Werror=type-limits]:
+// comparison is always true due to limited range of data type.
+template<typename T>
+inline bool IsOutRange(const T &v, const T &low, const T &high) {
+ return (v < low) || (high < v);
+}
+
+// Check 'v' is in closed range [low; high].
+template<typename T>
+inline bool IsInRange(const T &v, const T &low, const T &high) {
+ return !IsOutRange(v, low, high);
+}
+
} // namespace flatbuffers
#endif // FLATBUFFERS_BASE_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/buffer.h b/contrib/libs/flatbuffers/include/flatbuffers/buffer.h
new file mode 100644
index 0000000000..303367f39c
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/buffer.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2021 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_BUFFER_H_
+#define FLATBUFFERS_BUFFER_H_
+
+#include <algorithm>
+
+#include "base.h"
+
+namespace flatbuffers {
+
+// Wrapper for uoffset_t to allow safe template specialization.
+// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
+template<typename T = void> struct Offset {
+ // The type of offset to use.
+ typedef uoffset_t offset_type;
+
+ offset_type o;
+ Offset() : o(0) {}
+ Offset(const offset_type _o) : o(_o) {}
+ Offset<> Union() const { return o; }
+ bool IsNull() const { return !o; }
+};
+
+// Wrapper for uoffset64_t Offsets.
+template<typename T = void> struct Offset64 {
+ // The type of offset to use.
+ typedef uoffset64_t offset_type;
+
+ offset_type o;
+ Offset64() : o(0) {}
+ Offset64(const offset_type offset) : o(offset) {}
+ Offset64<> Union() const { return o; }
+ bool IsNull() const { return !o; }
+};
+
+// Litmus check for ensuring the Offsets are the expected size.
+static_assert(sizeof(Offset<>) == 4, "Offset has wrong size");
+static_assert(sizeof(Offset64<>) == 8, "Offset64 has wrong size");
+
+inline void EndianCheck() {
+ int endiantest = 1;
+ // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
+ FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
+ FLATBUFFERS_LITTLEENDIAN);
+ (void)endiantest;
+}
+
+template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
+ // clang-format off
+ #ifdef _MSC_VER
+ return __alignof(T);
+ #else
+ #ifndef alignof
+ return __alignof__(T);
+ #else
+ return alignof(T);
+ #endif
+ #endif
+ // clang-format on
+}
+
+// Lexicographically compare two strings (possibly containing nulls), and
+// return true if the first is less than the second.
+static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
+ const char *b_data, uoffset_t b_size) {
+ const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
+ return cmp == 0 ? a_size < b_size : cmp < 0;
+}
+
+// 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);
+
+ static return_type Read(const uint8_t *p, const size_t i) {
+ return EndianScalar((reinterpret_cast<const T *>(p))[i]);
+ }
+ static mutable_return_type Read(uint8_t *p, const size_t i) {
+ return reinterpret_cast<mutable_return_type>(
+ Read(const_cast<const uint8_t *>(p), i));
+ }
+};
+
+// For vector of Offsets.
+template<typename T, template<typename> class OffsetT>
+struct IndirectHelper<OffsetT<T>> {
+ typedef const T *return_type;
+ typedef T *mutable_return_type;
+ typedef typename OffsetT<T>::offset_type offset_type;
+ static const offset_type element_stride = sizeof(offset_type);
+
+ static return_type Read(const uint8_t *const p, const offset_type i) {
+ // Offsets are relative to themselves, so first update the pointer to
+ // point to the offset location.
+ const uint8_t *const offset_location = p + i * element_stride;
+
+ // Then read the scalar value of the offset (which may be 32 or 64-bits) and
+ // then determine the relative location from the offset location.
+ return reinterpret_cast<return_type>(
+ offset_location + ReadScalar<offset_type>(offset_location));
+ }
+ static mutable_return_type Read(uint8_t *const p, const offset_type i) {
+ // Offsets are relative to themselves, so first update the pointer to
+ // point to the offset location.
+ uint8_t *const offset_location = p + i * element_stride;
+
+ // Then read the scalar value of the offset (which may be 32 or 64-bits) and
+ // then determine the relative location from the offset location.
+ return reinterpret_cast<mutable_return_type>(
+ offset_location + ReadScalar<offset_type>(offset_location));
+ }
+};
+
+// For vector of structs.
+template<typename T> struct IndirectHelper<const T *> {
+ typedef const T *return_type;
+ typedef T *mutable_return_type;
+ static const size_t element_stride = sizeof(T);
+
+ static return_type Read(const uint8_t *const p, const size_t i) {
+ // Structs are stored inline, relative to the first struct pointer.
+ return reinterpret_cast<return_type>(p + i * element_stride);
+ }
+ static mutable_return_type Read(uint8_t *const p, const size_t i) {
+ // Structs are stored inline, relative to the first struct pointer.
+ return reinterpret_cast<mutable_return_type>(p + i * element_stride);
+ }
+};
+
+/// @brief Get a pointer to the file_identifier section of the buffer.
+/// @return Returns a const char pointer to the start of the file_identifier
+/// characters in the buffer. The returned char * has length
+/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
+/// This function is UNDEFINED for FlatBuffers whose schema does not include
+/// a file_identifier (likely points at padding or the start of a the root
+/// vtable).
+inline const char *GetBufferIdentifier(const void *buf,
+ bool size_prefixed = false) {
+ return reinterpret_cast<const char *>(buf) +
+ ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
+}
+
+// Helper to see if the identifier in a buffer has the expected value.
+inline bool BufferHasIdentifier(const void *buf, const char *identifier,
+ bool size_prefixed = false) {
+ return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
+ flatbuffers::kFileIdentifierLength) == 0;
+}
+
+/// @cond FLATBUFFERS_INTERNAL
+// Helpers to get a typed pointer to the root object contained in the buffer.
+template<typename T> T *GetMutableRoot(void *buf) {
+ if (!buf) return nullptr;
+ EndianCheck();
+ return reinterpret_cast<T *>(
+ reinterpret_cast<uint8_t *>(buf) +
+ EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
+}
+
+template<typename T, typename SizeT = uoffset_t>
+T *GetMutableSizePrefixedRoot(void *buf) {
+ return GetMutableRoot<T>(reinterpret_cast<uint8_t *>(buf) + sizeof(SizeT));
+}
+
+template<typename T> const T *GetRoot(const void *buf) {
+ return GetMutableRoot<T>(const_cast<void *>(buf));
+}
+
+template<typename T, typename SizeT = uoffset_t>
+const T *GetSizePrefixedRoot(const void *buf) {
+ return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(SizeT));
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BUFFER_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/buffer_ref.h b/contrib/libs/flatbuffers/include/flatbuffers/buffer_ref.h
new file mode 100644
index 0000000000..f2f865d37d
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/buffer_ref.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 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_BUFFER_REF_H_
+#define FLATBUFFERS_BUFFER_REF_H_
+
+#include "base.h"
+#include "verifier.h"
+
+namespace flatbuffers {
+
+// Convenient way to bundle a buffer and its length, to pass it around
+// typed by its root.
+// A BufferRef does not own its buffer.
+struct BufferRefBase {}; // for std::is_base_of
+
+template<typename T> struct BufferRef : BufferRefBase {
+ BufferRef() : buf(nullptr), len(0), must_free(false) {}
+ BufferRef(uint8_t *_buf, uoffset_t _len)
+ : buf(_buf), len(_len), must_free(false) {}
+
+ ~BufferRef() {
+ if (must_free) free(buf);
+ }
+
+ const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
+
+ bool Verify() {
+ Verifier verifier(buf, len);
+ return verifier.VerifyBuffer<T>(nullptr);
+ }
+
+ uint8_t *buf;
+ uoffset_t len;
+ bool must_free;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BUFFER_REF_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/code_generator.h b/contrib/libs/flatbuffers/include/flatbuffers/code_generator.h
new file mode 100644
index 0000000000..2c05b7e247
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/code_generator.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 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_GENERATOR_H_
+#define FLATBUFFERS_CODE_GENERATOR_H_
+
+#include <string>
+
+#include "idl.h"
+
+namespace flatbuffers {
+
+// A code generator interface for producing converting flatbuffer schema into
+// code.
+class CodeGenerator {
+ public:
+ virtual ~CodeGenerator() = default;
+
+ enum Status {
+ OK = 0,
+ ERROR = 1,
+ FAILED_VERIFICATION = 2,
+ NOT_IMPLEMENTED = 3
+ };
+
+ std::string status_detail;
+
+ // Generate code from the provided `parser`.
+ //
+ // DEPRECATED: prefer using the other overload of GenerateCode for bfbs.
+ virtual Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) = 0;
+
+ // Generate code from the provided `buffer` of given `length`. The buffer is a
+ // serialized reflection.fbs.
+ virtual Status GenerateCode(const uint8_t *buffer, int64_t length) = 0;
+
+ virtual Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) = 0;
+
+ virtual Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) = 0;
+
+ virtual Status GenerateRootFile(const Parser &parser,
+ const std::string &path) = 0;
+
+ virtual bool IsSchemaOnly() const = 0;
+
+ virtual bool SupportsBfbsGeneration() const = 0;
+
+ virtual bool SupportsRootFileGeneration() const = 0;
+
+ virtual IDLOptions::Language Language() const = 0;
+
+ virtual std::string LanguageName() const = 0;
+
+ protected:
+ CodeGenerator() = default;
+
+ private:
+ // Copying is not supported.
+ CodeGenerator(const CodeGenerator &) = delete;
+ CodeGenerator &operator=(const CodeGenerator &) = delete;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_CODE_GENERATOR_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h
index 09b773a468..0407690616 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h
@@ -97,8 +97,6 @@ class BaseGenerator {
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;
@@ -140,7 +138,8 @@ class BaseGenerator {
std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) const;
- std::string WrapInNameSpace(const Definition &def) const;
+ std::string WrapInNameSpace(const Definition &def,
+ const std::string &suffix = "") const;
std::string GetNameSpace(const Definition &def) const;
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/default_allocator.h b/contrib/libs/flatbuffers/include/flatbuffers/default_allocator.h
new file mode 100644
index 0000000000..e638b990b8
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/default_allocator.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 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_DEFAULT_ALLOCATOR_H_
+#define FLATBUFFERS_DEFAULT_ALLOCATOR_H_
+
+#include "allocator.h"
+#include "base.h"
+
+namespace flatbuffers {
+
+// DefaultAllocator uses new/delete to allocate memory regions
+class DefaultAllocator : public Allocator {
+ public:
+ uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
+ return new uint8_t[size];
+ }
+
+ void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
+
+ static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
+};
+
+// These functions allow for a null allocator to mean use the default allocator,
+// as used by DetachedBuffer and vector_downward below.
+// This is to avoid having a statically or dynamically allocated default
+// allocator, or having to move it between the classes that may own it.
+inline uint8_t *Allocate(Allocator *allocator, size_t size) {
+ return allocator ? allocator->allocate(size)
+ : DefaultAllocator().allocate(size);
+}
+
+inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
+ if (allocator)
+ allocator->deallocate(p, size);
+ else
+ DefaultAllocator().deallocate(p, size);
+}
+
+inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
+ size_t old_size, size_t new_size,
+ size_t in_use_back, size_t in_use_front) {
+ return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
+ in_use_back, in_use_front)
+ : DefaultAllocator().reallocate_downward(
+ old_p, old_size, new_size, in_use_back, in_use_front);
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_DEFAULT_ALLOCATOR_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/detached_buffer.h b/contrib/libs/flatbuffers/include/flatbuffers/detached_buffer.h
new file mode 100644
index 0000000000..0d1ada76e3
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/detached_buffer.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2021 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_DETACHED_BUFFER_H_
+#define FLATBUFFERS_DETACHED_BUFFER_H_
+
+#include "allocator.h"
+#include "base.h"
+#include "default_allocator.h"
+
+namespace flatbuffers {
+
+// DetachedBuffer is a finished flatbuffer memory region, detached from its
+// builder. The original memory region and allocator are also stored so that
+// the DetachedBuffer can manage the memory lifetime.
+class DetachedBuffer {
+ public:
+ DetachedBuffer()
+ : allocator_(nullptr),
+ own_allocator_(false),
+ buf_(nullptr),
+ reserved_(0),
+ cur_(nullptr),
+ size_(0) {}
+
+ DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
+ size_t reserved, uint8_t *cur, size_t sz)
+ : allocator_(allocator),
+ own_allocator_(own_allocator),
+ buf_(buf),
+ reserved_(reserved),
+ cur_(cur),
+ size_(sz) {}
+
+ DetachedBuffer(DetachedBuffer &&other) noexcept
+ : allocator_(other.allocator_),
+ own_allocator_(other.own_allocator_),
+ buf_(other.buf_),
+ reserved_(other.reserved_),
+ cur_(other.cur_),
+ size_(other.size_) {
+ other.reset();
+ }
+
+ DetachedBuffer &operator=(DetachedBuffer &&other) noexcept {
+ if (this == &other) return *this;
+
+ destroy();
+
+ allocator_ = other.allocator_;
+ own_allocator_ = other.own_allocator_;
+ buf_ = other.buf_;
+ reserved_ = other.reserved_;
+ cur_ = other.cur_;
+ size_ = other.size_;
+
+ other.reset();
+
+ return *this;
+ }
+
+ ~DetachedBuffer() { destroy(); }
+
+ const uint8_t *data() const { return cur_; }
+
+ uint8_t *data() { return cur_; }
+
+ size_t size() const { return size_; }
+
+ // These may change access mode, leave these at end of public section
+ FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other));
+ FLATBUFFERS_DELETE_FUNC(
+ DetachedBuffer &operator=(const DetachedBuffer &other));
+
+ protected:
+ Allocator *allocator_;
+ bool own_allocator_;
+ uint8_t *buf_;
+ size_t reserved_;
+ uint8_t *cur_;
+ size_t size_;
+
+ inline void destroy() {
+ if (buf_) Deallocate(allocator_, buf_, reserved_);
+ if (own_allocator_ && allocator_) { delete allocator_; }
+ reset();
+ }
+
+ inline void reset() {
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ buf_ = nullptr;
+ reserved_ = 0;
+ cur_ = nullptr;
+ size_ = 0;
+ }
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_DETACHED_BUFFER_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/file_manager.h b/contrib/libs/flatbuffers/include/flatbuffers/file_manager.h
new file mode 100644
index 0000000000..b19ba91f15
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/file_manager.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 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_FILE_MANAGER_H_
+#define FLATBUFFERS_FILE_MANAGER_H_
+
+#include <set>
+#include <string>
+
+#include "util.h"
+
+namespace flatbuffers {
+
+// A File interface to write data to file by default or
+// save only file names
+class FileManager {
+ public:
+ FileManager() = default;
+ virtual ~FileManager() = default;
+
+ virtual bool SaveFile(const std::string &absolute_file_name,
+ const std::string &content) = 0;
+
+ virtual bool LoadFile(const std::string &absolute_file_name,
+ std::string *buf) = 0;
+
+ private:
+ // Copying is not supported.
+ FileManager(const FileManager &) = delete;
+ FileManager &operator=(const FileManager &) = delete;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_FILE_MANAGER_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h
new file mode 100644
index 0000000000..4bb2a7222a
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h
@@ -0,0 +1,1471 @@
+/*
+ * Copyright 2021 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_FLATBUFFER_BUILDER_H_
+#define FLATBUFFERS_FLATBUFFER_BUILDER_H_
+
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <initializer_list>
+#include <type_traits>
+
+#include "allocator.h"
+#include "array.h"
+#include "base.h"
+#include "buffer.h"
+#include "buffer_ref.h"
+#include "default_allocator.h"
+#include "detached_buffer.h"
+#include "stl_emulation.h"
+#include "string.h"
+#include "struct.h"
+#include "table.h"
+#include "vector.h"
+#include "vector_downward.h"
+#include "verifier.h"
+
+namespace flatbuffers {
+
+// 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 voffset_t fixed_fields =
+ 2 * sizeof(voffset_t); // Vtable size and Object Size.
+ return fixed_fields + field_id * sizeof(voffset_t);
+}
+
+template<typename T, typename Alloc = std::allocator<T>>
+const T *data(const std::vector<T, Alloc> &v) {
+ // Eventually the returned pointer gets passed down to memcpy, so
+ // we need it to be non-null to avoid undefined behavior.
+ static uint8_t t;
+ return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
+}
+template<typename T, typename Alloc = std::allocator<T>>
+T *data(std::vector<T, Alloc> &v) {
+ // Eventually the returned pointer gets passed down to memcpy, so
+ // we need it to be non-null to avoid undefined behavior.
+ static uint8_t t;
+ return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
+}
+
+/// @addtogroup flatbuffers_cpp_api
+/// @{
+/// @class FlatBufferBuilder
+/// @brief Helper class to hold data needed in creation of a FlatBuffer.
+/// To serialize data, you typically call one of the `Create*()` functions in
+/// the generated code, which in turn call a sequence of `StartTable`/
+/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
+/// `CreateVector` functions. Do this is depth-first order to build up a tree to
+/// the root. `Finish()` wraps up the buffer ready for transport.
+template<bool Is64Aware = false> class FlatBufferBuilderImpl {
+ public:
+ // This switches the size type of the builder, based on if its 64-bit aware
+ // (uoffset64_t) or not (uoffset_t).
+ typedef
+ typename std::conditional<Is64Aware, uoffset64_t, uoffset_t>::type SizeT;
+
+ /// @brief Default constructor for FlatBufferBuilder.
+ /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
+ /// to `1024`.
+ /// @param[in] allocator An `Allocator` to use. If null will use
+ /// `DefaultAllocator`.
+ /// @param[in] own_allocator Whether the builder/vector should own the
+ /// allocator. Defaults to / `false`.
+ /// @param[in] buffer_minalign Force the buffer to be aligned to the given
+ /// minimum alignment upon reallocation. Only needed if you intend to store
+ /// types with custom alignment AND you wish to read the buffer in-place
+ /// directly after creation.
+ explicit FlatBufferBuilderImpl(
+ size_t initial_size = 1024, Allocator *allocator = nullptr,
+ bool own_allocator = false,
+ size_t buffer_minalign = AlignOf<largest_scalar_t>())
+ : buf_(initial_size, allocator, own_allocator, buffer_minalign,
+ static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
+ : FLATBUFFERS_MAX_BUFFER_SIZE)),
+ num_field_loc(0),
+ max_voffset_(0),
+ length_of_64_bit_region_(0),
+ nested(false),
+ finished(false),
+ minalign_(1),
+ force_defaults_(false),
+ dedup_vtables_(true),
+ string_pool(nullptr) {
+ EndianCheck();
+ }
+
+ /// @brief Move constructor for FlatBufferBuilder.
+ FlatBufferBuilderImpl(FlatBufferBuilderImpl &&other) noexcept
+ : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>(),
+ static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
+ : FLATBUFFERS_MAX_BUFFER_SIZE)),
+ num_field_loc(0),
+ max_voffset_(0),
+ length_of_64_bit_region_(0),
+ nested(false),
+ finished(false),
+ minalign_(1),
+ force_defaults_(false),
+ dedup_vtables_(true),
+ string_pool(nullptr) {
+ EndianCheck();
+ // Default construct and swap idiom.
+ // Lack of delegating constructors in vs2010 makes it more verbose than
+ // needed.
+ Swap(other);
+ }
+
+ /// @brief Move assignment operator for FlatBufferBuilder.
+ FlatBufferBuilderImpl &operator=(FlatBufferBuilderImpl &&other) noexcept {
+ // Move construct a temporary and swap idiom
+ FlatBufferBuilderImpl temp(std::move(other));
+ Swap(temp);
+ return *this;
+ }
+
+ void Swap(FlatBufferBuilderImpl &other) {
+ using std::swap;
+ buf_.swap(other.buf_);
+ swap(num_field_loc, other.num_field_loc);
+ swap(max_voffset_, other.max_voffset_);
+ swap(length_of_64_bit_region_, other.length_of_64_bit_region_);
+ swap(nested, other.nested);
+ swap(finished, other.finished);
+ swap(minalign_, other.minalign_);
+ swap(force_defaults_, other.force_defaults_);
+ swap(dedup_vtables_, other.dedup_vtables_);
+ swap(string_pool, other.string_pool);
+ }
+
+ ~FlatBufferBuilderImpl() {
+ if (string_pool) delete string_pool;
+ }
+
+ void Reset() {
+ Clear(); // clear builder state
+ buf_.reset(); // deallocate buffer
+ }
+
+ /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
+ /// to construct another buffer.
+ void Clear() {
+ ClearOffsets();
+ buf_.clear();
+ nested = false;
+ finished = false;
+ minalign_ = 1;
+ length_of_64_bit_region_ = 0;
+ if (string_pool) string_pool->clear();
+ }
+
+ /// @brief The current size of the serialized buffer, counting from the end.
+ /// @return Returns an `SizeT` with the current size of the buffer.
+ SizeT GetSize() const { return buf_.size(); }
+
+ /// @brief The current size of the serialized buffer relative to the end of
+ /// the 32-bit region.
+ /// @return Returns an `uoffset_t` with the current size of the buffer.
+ template<bool is_64 = Is64Aware>
+ // Only enable this method for the 64-bit builder, as only that builder is
+ // concerned with the 32/64-bit boundary, and should be the one to bare any
+ // run time costs.
+ typename std::enable_if<is_64, uoffset_t>::type GetSizeRelative32BitRegion()
+ const {
+ //[32-bit region][64-bit region]
+ // [XXXXXXXXXXXXXXXXXXX] GetSize()
+ // [YYYYYYYYYYYYY] length_of_64_bit_region_
+ // [ZZZZ] return size
+ return static_cast<uoffset_t>(GetSize() - length_of_64_bit_region_);
+ }
+
+ template<bool is_64 = Is64Aware>
+ // Only enable this method for the 32-bit builder.
+ typename std::enable_if<!is_64, uoffset_t>::type GetSizeRelative32BitRegion()
+ const {
+ return static_cast<uoffset_t>(GetSize());
+ }
+
+ /// @brief Get the serialized buffer (after you call `Finish()`).
+ /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
+ /// buffer.
+ uint8_t *GetBufferPointer() const {
+ Finished();
+ return buf_.data();
+ }
+
+ /// @brief Get the serialized buffer (after you call `Finish()`) as a span.
+ /// @return Returns a constructed flatbuffers::span that is a view over the
+ /// FlatBuffer data inside the buffer.
+ flatbuffers::span<uint8_t> GetBufferSpan() const {
+ Finished();
+ return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
+ }
+
+ /// @brief Get a pointer to an unfinished buffer.
+ /// @return Returns a `uint8_t` pointer to the unfinished buffer.
+ uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
+
+ /// @brief Get the released pointer to the serialized buffer.
+ /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
+ /// @return A `FlatBuffer` that owns the buffer and its allocator and
+ /// behaves similar to a `unique_ptr` with a deleter.
+ FLATBUFFERS_ATTRIBUTE([[deprecated("use Release() instead")]])
+ DetachedBuffer ReleaseBufferPointer() {
+ Finished();
+ return buf_.release();
+ }
+
+ /// @brief Get the released DetachedBuffer.
+ /// @return A `DetachedBuffer` that owns the buffer and its allocator.
+ DetachedBuffer Release() {
+ Finished();
+ return buf_.release();
+ }
+
+ /// @brief Get the released pointer to the serialized buffer.
+ /// @param size The size of the memory block containing
+ /// the serialized `FlatBuffer`.
+ /// @param offset The offset from the released pointer where the finished
+ /// `FlatBuffer` starts.
+ /// @return A raw pointer to the start of the memory block containing
+ /// the serialized `FlatBuffer`.
+ /// @remark If the allocator is owned, it gets deleted when the destructor is
+ /// called..
+ uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
+ Finished();
+ return buf_.release_raw(size, offset);
+ }
+
+ /// @brief get the minimum alignment this buffer needs to be accessed
+ /// properly. This is only known once all elements have been written (after
+ /// you call Finish()). You can use this information if you need to embed
+ /// a FlatBuffer in some other buffer, such that you can later read it
+ /// without first having to copy it into its own buffer.
+ size_t GetBufferMinAlignment() const {
+ Finished();
+ return minalign_;
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ 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
+ // FlatBufferBuilder::Finish with your root table.
+ // If you really need to access an unfinished buffer, call
+ // GetCurrentBufferPointer instead.
+ FLATBUFFERS_ASSERT(finished);
+ }
+ /// @endcond
+
+ /// @brief In order to save space, fields that are set to their default value
+ /// don't get serialized into the buffer.
+ /// @param[in] fd When set to `true`, always serializes default values that
+ /// are set. Optional fields which are not set explicitly, will still not be
+ /// serialized.
+ void ForceDefaults(bool fd) { force_defaults_ = fd; }
+
+ /// @brief By default vtables are deduped in order to save space.
+ /// @param[in] dedup When set to `true`, dedup vtables.
+ void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
+
+ void TrackMinAlign(size_t elem_size) {
+ if (elem_size > minalign_) minalign_ = elem_size;
+ }
+
+ void Align(size_t elem_size) {
+ TrackMinAlign(elem_size);
+ buf_.fill(PaddingBytes(buf_.size(), elem_size));
+ }
+
+ void PushFlatBuffer(const uint8_t *bytes, size_t size) {
+ PushBytes(bytes, size);
+ finished = true;
+ }
+
+ void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
+
+ void PopBytes(size_t amount) { buf_.pop(amount); }
+
+ template<typename T> void AssertScalarT() {
+ // The code assumes power of 2 sizes and endian-swap-ability.
+ static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
+ }
+
+ // Write a single aligned scalar to the buffer
+ template<typename T, typename ReturnT = uoffset_t>
+ ReturnT PushElement(T element) {
+ AssertScalarT<T>();
+ Align(sizeof(T));
+ buf_.push_small(EndianScalar(element));
+ return CalculateOffset<ReturnT>();
+ }
+
+ template<typename T, template<typename> class OffsetT = Offset>
+ uoffset_t PushElement(OffsetT<T> off) {
+ // Special case for offsets: see ReferTo below.
+ return PushElement(ReferTo(off.o));
+ }
+
+ // When writing fields, we track where they are, so we can create correct
+ // vtables later.
+ void TrackField(voffset_t field, uoffset_t off) {
+ FieldLoc fl = { off, field };
+ buf_.scratch_push_small(fl);
+ num_field_loc++;
+ if (field > max_voffset_) { max_voffset_ = field; }
+ }
+
+ // Like PushElement, but additionally tracks the field this represents.
+ template<typename T> void AddElement(voffset_t field, T e, T def) {
+ // We don't serialize values equal to the default.
+ if (IsTheSameAs(e, def) && !force_defaults_) return;
+ TrackField(field, PushElement(e));
+ }
+
+ template<typename T> void AddElement(voffset_t field, T e) {
+ TrackField(field, PushElement(e));
+ }
+
+ template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
+ if (off.IsNull()) return; // Don't store.
+ AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
+ }
+
+ template<typename T> void AddOffset(voffset_t field, Offset64<T> off) {
+ if (off.IsNull()) return; // Don't store.
+ AddElement(field, ReferTo(off.o), static_cast<uoffset64_t>(0));
+ }
+
+ template<typename T> void AddStruct(voffset_t field, const T *structptr) {
+ if (!structptr) return; // Default, don't store.
+ Align(AlignOf<T>());
+ buf_.push_small(*structptr);
+ TrackField(field, CalculateOffset<uoffset_t>());
+ }
+
+ void AddStructOffset(voffset_t field, uoffset_t off) {
+ TrackField(field, off);
+ }
+
+ // Offsets initially are relative to the end of the buffer (downwards).
+ // This function converts them to be relative to the current location
+ // in the buffer (when stored here), pointing upwards.
+ uoffset_t ReferTo(uoffset_t off) {
+ // Align to ensure GetSizeRelative32BitRegion() below is correct.
+ Align(sizeof(uoffset_t));
+ // 32-bit offsets are relative to the tail of the 32-bit region of the
+ // buffer. For most cases (without 64-bit entities) this is equivalent to
+ // size of the whole buffer (e.g. GetSize())
+ return ReferTo(off, GetSizeRelative32BitRegion());
+ }
+
+ uoffset64_t ReferTo(uoffset64_t off) {
+ // Align to ensure GetSize() below is correct.
+ Align(sizeof(uoffset64_t));
+ // 64-bit offsets are relative to tail of the whole buffer
+ return ReferTo(off, GetSize());
+ }
+
+ template<typename T, typename T2> T ReferTo(const T off, const T2 size) {
+ FLATBUFFERS_ASSERT(off && off <= size);
+ return size - off + static_cast<T>(sizeof(T));
+ }
+
+ template<typename T> T ReferTo(const T off, const T size) {
+ FLATBUFFERS_ASSERT(off && off <= size);
+ return size - off + static_cast<T>(sizeof(T));
+ }
+
+ void NotNested() {
+ // If you hit this, you're trying to construct a Table/Vector/String
+ // during the construction of its parent table (between the MyTableBuilder
+ // and table.Finish().
+ // Move the creation of these sub-objects to above the MyTableBuilder to
+ // not get this assert.
+ // Ignoring this assert may appear to work in simple cases, but the reason
+ // it is here is that storing objects in-line may cause vtable offsets
+ // to not fit anymore. It also leads to vtable duplication.
+ FLATBUFFERS_ASSERT(!nested);
+ // If you hit this, fields were added outside the scope of a table.
+ FLATBUFFERS_ASSERT(!num_field_loc);
+ }
+
+ // From generated code (or from the parser), we call StartTable/EndTable
+ // with a sequence of AddElement calls in between.
+ uoffset_t StartTable() {
+ NotNested();
+ nested = true;
+ return GetSizeRelative32BitRegion();
+ }
+
+ // This finishes one serialized object by generating the vtable if it's a
+ // table, comparing it against existing vtables, and writing the
+ // resulting vtable offset.
+ uoffset_t EndTable(uoffset_t start) {
+ // If you get this assert, a corresponding StartTable wasn't called.
+ FLATBUFFERS_ASSERT(nested);
+ // Write the vtable offset, which is the start of any Table.
+ // We fill its value later.
+ // This is relative to the end of the 32-bit region.
+ const uoffset_t vtable_offset_loc =
+ static_cast<uoffset_t>(PushElement<soffset_t>(0));
+ // Write a vtable, which consists entirely of voffset_t elements.
+ // It starts with the number of offsets, followed by a type id, followed
+ // by the offsets themselves. In reverse:
+ // Include space for the last offset and ensure empty tables have a
+ // minimum size.
+ max_voffset_ =
+ (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
+ FieldIndexToOffset(0));
+ buf_.fill_big(max_voffset_);
+ const uoffset_t table_object_size = vtable_offset_loc - start;
+ // Vtable use 16bit offsets.
+ FLATBUFFERS_ASSERT(table_object_size < 0x10000);
+ WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
+ static_cast<voffset_t>(table_object_size));
+ WriteScalar<voffset_t>(buf_.data(), max_voffset_);
+ // Write the offsets into the table
+ for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
+ it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
+ auto field_location = reinterpret_cast<FieldLoc *>(it);
+ const voffset_t pos =
+ static_cast<voffset_t>(vtable_offset_loc - field_location->off);
+ // If this asserts, it means you've set a field twice.
+ FLATBUFFERS_ASSERT(
+ !ReadScalar<voffset_t>(buf_.data() + field_location->id));
+ WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
+ }
+ ClearOffsets();
+ auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
+ auto vt1_size = ReadScalar<voffset_t>(vt1);
+ auto vt_use = GetSizeRelative32BitRegion();
+ // See if we already have generated a vtable with this exact same
+ // layout before. If so, make it point to the old one, remove this one.
+ if (dedup_vtables_) {
+ for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
+ it += sizeof(uoffset_t)) {
+ auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
+ auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
+ auto vt2_size = ReadScalar<voffset_t>(vt2);
+ if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
+ vt_use = *vt_offset_ptr;
+ buf_.pop(GetSizeRelative32BitRegion() - vtable_offset_loc);
+ break;
+ }
+ }
+ // If this is a new vtable, remember it.
+ if (vt_use == GetSizeRelative32BitRegion()) {
+ buf_.scratch_push_small(vt_use);
+ }
+ // Fill the vtable offset we created above.
+ // The offset points from the beginning of the object to where the vtable is
+ // stored.
+ // Offsets default direction is downward in memory for future format
+ // flexibility (storing all vtables at the start of the file).
+ WriteScalar(buf_.data_at(vtable_offset_loc + length_of_64_bit_region_),
+ static_cast<soffset_t>(vt_use) -
+ static_cast<soffset_t>(vtable_offset_loc));
+ nested = false;
+ return vtable_offset_loc;
+ }
+
+ FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
+ uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
+ return EndTable(start);
+ }
+
+ // This checks a required field has been set in a given table that has
+ // just been constructed.
+ template<typename T> void Required(Offset<T> table, voffset_t field) {
+ auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
+ bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
+ // If this fails, the caller will show what field needs to be set.
+ FLATBUFFERS_ASSERT(ok);
+ (void)ok;
+ }
+
+ uoffset_t StartStruct(size_t alignment) {
+ Align(alignment);
+ return GetSizeRelative32BitRegion();
+ }
+
+ uoffset_t EndStruct() { return GetSizeRelative32BitRegion(); }
+
+ void ClearOffsets() {
+ buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
+ num_field_loc = 0;
+ max_voffset_ = 0;
+ }
+
+ // Aligns such that when "len" bytes are written, an object can be written
+ // after it (forward in the buffer) with "alignment" without padding.
+ void PreAlign(size_t len, size_t alignment) {
+ if (len == 0) return;
+ TrackMinAlign(alignment);
+ buf_.fill(PaddingBytes(GetSize() + len, alignment));
+ }
+
+ // Aligns such than when "len" bytes are written, an object of type `AlignT`
+ // can be written after it (forward in the buffer) without padding.
+ template<typename AlignT> void PreAlign(size_t len) {
+ AssertScalarT<AlignT>();
+ PreAlign(len, AlignOf<AlignT>());
+ }
+ /// @endcond
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const char pointer to the data to be stored as a string.
+ /// @param[in] len The number of bytes that should be stored from `str`.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template<typename> class OffsetT = Offset>
+ OffsetT<String> CreateString(const char *str, size_t len) {
+ CreateStringImpl(str, len);
+ return OffsetT<String>(
+ CalculateOffset<typename OffsetT<String>::offset_type>());
+ }
+
+ /// @brief Store a string in the buffer, which is null-terminated.
+ /// @param[in] str A const char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template<typename> class OffsetT = Offset>
+ OffsetT<String> CreateString(const char *str) {
+ return CreateString<OffsetT>(str, strlen(str));
+ }
+
+ /// @brief Store a string in the buffer, which is null-terminated.
+ /// @param[in] str A char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template<typename> class OffsetT = Offset>
+ OffsetT<String> CreateString(char *str) {
+ return CreateString<OffsetT>(str, strlen(str));
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const reference to a std::string to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template<typename> class OffsetT = Offset>
+ OffsetT<String> CreateString(const std::string &str) {
+ return CreateString<OffsetT>(str.c_str(), str.length());
+ }
+
+ // clang-format off
+ #ifdef FLATBUFFERS_HAS_STRING_VIEW
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const string_view to copy in to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template <typename> class OffsetT = Offset>
+ OffsetT<String>CreateString(flatbuffers::string_view str) {
+ return CreateString<OffsetT>(str.data(), str.size());
+ }
+ #endif // FLATBUFFERS_HAS_STRING_VIEW
+ // clang-format on
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ template<template<typename> class OffsetT = Offset>
+ OffsetT<String> CreateString(const String *str) {
+ return str ? CreateString<OffsetT>(str->c_str(), str->size()) : 0;
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const reference to a std::string like type with support
+ /// of T::c_str() and T::length() to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ template<template<typename> class OffsetT = Offset,
+ // No need to explicitly declare the T type, let the compiler deduce
+ // it.
+ int &...ExplicitArgumentBarrier, typename T>
+ OffsetT<String> CreateString(const T &str) {
+ return CreateString<OffsetT>(str.data(), str.length());
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string. This uses a map
+ /// stored on the heap, but only stores the numerical offsets.
+ /// @param[in] str A const char pointer to the data to be stored as a string.
+ /// @param[in] len The number of bytes that should be stored from `str`.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const char *str, size_t len) {
+ FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
+ if (!string_pool) {
+ string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
+ }
+
+ const size_t size_before_string = buf_.size();
+ // Must first serialize the string, since the set is all offsets into
+ // buffer.
+ const Offset<String> off = CreateString<Offset>(str, len);
+ auto it = string_pool->find(off);
+ // If it exists we reuse existing serialized data!
+ if (it != string_pool->end()) {
+ // We can remove the string we serialized.
+ buf_.pop(buf_.size() - size_before_string);
+ return *it;
+ }
+ // Record this string for future use.
+ string_pool->insert(off);
+ return off;
+ }
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string. This uses a map
+ /// stored on the heap, but only stores the numerical offsets.
+ /// @param[in] str A const std::string_view to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ Offset<String> CreateSharedString(const flatbuffers::string_view str) {
+ return CreateSharedString(str.data(), str.size());
+ }
+#else
+ /// @brief Store a string in the buffer, which null-terminated.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string. This uses a map
+ /// stored on the heap, but only stores the numerical offsets.
+ /// @param[in] str A const char pointer to a C-string to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const char *str) {
+ return CreateSharedString(str, strlen(str));
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string. This uses a map
+ /// stored on the heap, but only stores the numerical offsets.
+ /// @param[in] str A const reference to a std::string to store in the buffer.
+ /// @return Returns the offset in the buffer where the string starts.
+ Offset<String> CreateSharedString(const std::string &str) {
+ return CreateSharedString(str.c_str(), str.length());
+ }
+#endif
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// If a string with this exact contents has already been serialized before,
+ /// instead simply returns the offset of the existing string. This uses a map
+ /// stored on the heap, but only stores the numerical offsets.
+ /// @param[in] str A const pointer to a `String` struct to add to the buffer.
+ /// @return Returns the offset in the buffer where the string starts
+ Offset<String> CreateSharedString(const String *str) {
+ return str ? CreateSharedString(str->c_str(), str->size()) : 0;
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ template<typename LenT = uoffset_t, typename ReturnT = uoffset_t>
+ ReturnT EndVector(size_t len) {
+ FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector.
+ nested = false;
+ return PushElement<LenT, ReturnT>(static_cast<LenT>(len));
+ }
+
+ template<template<typename> class OffsetT = Offset, typename LenT = uint32_t>
+ void StartVector(size_t len, size_t elemsize, size_t alignment) {
+ NotNested();
+ nested = true;
+ // Align to the Length type of the vector (either 32-bit or 64-bit), so
+ // that the length of the buffer can be added without padding.
+ PreAlign<LenT>(len * elemsize);
+ PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t.
+ }
+
+ template<typename T, template<typename> class OffsetT = Offset,
+ typename LenT = uint32_t>
+ void StartVector(size_t len) {
+ return StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
+ }
+
+ // Call this right before StartVector/CreateVector if you want to force the
+ // alignment to be something different than what the element size would
+ // normally dictate.
+ // This is useful when storing a nested_flatbuffer in a vector of bytes,
+ // or when storing SIMD floats, etc.
+ void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
+ if (len == 0) return;
+ FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
+ PreAlign(len * elemsize, alignment);
+ }
+
+ // Similar to ForceVectorAlignment but for String fields.
+ void ForceStringAlignment(size_t len, size_t alignment) {
+ if (len == 0) return;
+ FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
+ PreAlign((len + 1) * sizeof(char), alignment);
+ }
+
+ /// @endcond
+
+ /// @brief Serialize an array into a FlatBuffer `vector`.
+ /// @tparam T The data type of the array elements.
+ /// @tparam OffsetT the type of offset to return
+ /// @tparam VectorT the type of vector to cast to.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `TOffset` into the serialized data indicating
+ /// where the vector is stored.
+ template<template<typename...> class OffsetT = Offset,
+ template<typename...> class VectorT = Vector,
+ int &...ExplicitArgumentBarrier, typename T>
+ OffsetT<VectorT<T>> CreateVector(const T *v, size_t len) {
+ // The type of the length field in the vector.
+ typedef typename VectorT<T>::size_type LenT;
+ typedef typename OffsetT<VectorT<T>>::offset_type offset_type;
+ // If this assert hits, you're specifying a template argument that is
+ // causing the wrong overload to be selected, remove it.
+ AssertScalarT<T>();
+ StartVector<T, OffsetT, LenT>(len);
+ if (len > 0) {
+ // clang-format off
+ #if FLATBUFFERS_LITTLEENDIAN
+ PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
+ #else
+ if (sizeof(T) == 1) {
+ PushBytes(reinterpret_cast<const uint8_t *>(v), len);
+ } else {
+ for (auto i = len; i > 0; ) {
+ PushElement(v[--i]);
+ }
+ }
+ #endif
+ // clang-format on
+ }
+ return OffsetT<VectorT<T>>(EndVector<LenT, offset_type>(len));
+ }
+
+ /// @brief Serialize an array like object into a FlatBuffer `vector`.
+ /// @tparam T The data type of the array elements.
+ /// @tparam C The type of the array.
+ /// @param[in] array A reference to an array like object of type `T` to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, class C> Offset<Vector<T>> CreateVector(const C &array) {
+ return CreateVector(array.data(), array.size());
+ }
+
+ /// @brief Serialize an initializer list into a FlatBuffer `vector`.
+ /// @tparam T The data type of the initializer list elements.
+ /// @param[in] v The value of the initializer list.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T>
+ Offset<Vector<T>> CreateVector(std::initializer_list<T> v) {
+ return CreateVector(v.begin(), v.size());
+ }
+
+ template<typename T>
+ Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
+ StartVector<Offset<T>>(len);
+ for (auto i = len; i > 0;) { PushElement(v[--i]); }
+ return Offset<Vector<Offset<T>>>(EndVector(len));
+ }
+
+ /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param v A const reference to the `std::vector` to serialize into the
+ /// buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename Alloc = std::allocator<T>>
+ Offset<Vector<T>> CreateVector(const std::vector<T, Alloc> &v) {
+ return CreateVector(data(v), v.size());
+ }
+
+ template<template<typename...> class VectorT = Vector64,
+ int &...ExplicitArgumentBarrier, typename T>
+ Offset64<VectorT<T>> CreateVector64(const std::vector<T> &v) {
+ return CreateVector<Offset64, VectorT>(data(v), v.size());
+ }
+
+ // vector<bool> may be implemented using a bit-set, so we can't access it as
+ // an array. Instead, read elements manually.
+ // Background: https://isocpp.org/blog/2012/11/on-vectorbool
+ Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
+ StartVector<uint8_t>(v.size());
+ for (auto i = v.size(); i > 0;) {
+ PushElement(static_cast<uint8_t>(v[--i]));
+ }
+ return Offset<Vector<uint8_t>>(EndVector(v.size()));
+ }
+
+ /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+ /// This is a convenience function that takes care of iteration for you.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param f A function that takes the current iteration 0..vector_size-1 and
+ /// returns any type that you can construct a FlatBuffers vector out of.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T>
+ Offset<Vector<T>> CreateVector(size_t vector_size,
+ const std::function<T(size_t i)> &f) {
+ FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
+ std::vector<T> elems(vector_size);
+ for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
+ return CreateVector(elems);
+ }
+
+ /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
+ /// This is a convenience function that takes care of iteration for you. This
+ /// uses a vector stored on the heap to store the intermediate results of the
+ /// iteration.
+ /// @tparam T The data type of the `std::vector` elements.
+ /// @param f A function that takes the current iteration 0..vector_size-1,
+ /// and the state parameter returning any type that you can construct a
+ /// FlatBuffers vector out of.
+ /// @param state State passed to f.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename F, typename S>
+ Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
+ FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
+ std::vector<T> elems(vector_size);
+ for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
+ return CreateVector(elems);
+ }
+
+ /// @brief Serialize a `std::vector<StringType>` into a FlatBuffer `vector`.
+ /// whereas StringType is any type that is accepted by the CreateString()
+ /// overloads.
+ /// This is a convenience function for a common case.
+ /// @param v A const reference to the `std::vector` to serialize into the
+ /// buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename StringType = std::string,
+ typename Alloc = std::allocator<StringType>>
+ Offset<Vector<Offset<String>>> CreateVectorOfStrings(
+ const std::vector<StringType, Alloc> &v) {
+ return CreateVectorOfStrings(v.cbegin(), v.cend());
+ }
+
+ /// @brief Serialize a collection of Strings into a FlatBuffer `vector`.
+ /// This is a convenience function for a common case.
+ /// @param begin The beginning iterator of the collection
+ /// @param end The ending iterator of the collection
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<class It>
+ Offset<Vector<Offset<String>>> CreateVectorOfStrings(It begin, It end) {
+ auto size = std::distance(begin, end);
+ auto scratch_buffer_usage = size * sizeof(Offset<String>);
+ // If there is not enough space to store the offsets, there definitely won't
+ // be enough space to store all the strings. So ensuring space for the
+ // scratch region is OK, for if it fails, it would have failed later.
+ buf_.ensure_space(scratch_buffer_usage);
+ for (auto it = begin; it != end; ++it) {
+ buf_.scratch_push_small(CreateString(*it));
+ }
+ StartVector<Offset<String>>(size);
+ for (auto i = 1; i <= size; i++) {
+ // Note we re-evaluate the buf location each iteration to account for any
+ // underlying buffer resizing that may occur.
+ PushElement(*reinterpret_cast<Offset<String> *>(
+ buf_.scratch_end() - i * sizeof(Offset<String>)));
+ }
+ buf_.scratch_pop(scratch_buffer_usage);
+ return Offset<Vector<Offset<String>>>(EndVector(size));
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, template<typename...> class OffsetT = Offset,
+ template<typename...> class VectorT = Vector>
+ OffsetT<VectorT<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
+ // The type of the length field in the vector.
+ typedef typename VectorT<T>::size_type LenT;
+ typedef typename OffsetT<VectorT<const T *>>::offset_type offset_type;
+
+ StartVector<OffsetT, LenT>(len * sizeof(T) / AlignOf<T>(), sizeof(T),
+ AlignOf<T>());
+ if (len > 0) {
+ PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
+ }
+ return OffsetT<VectorT<const T *>>(EndVector<LenT, offset_type>(len));
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] filler A function that takes the current iteration
+ /// 0..vector_size-1 and a pointer to the struct that must be filled.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ /// This is mostly useful when flatbuffers are generated with mutation
+ /// accessors.
+ template<typename T>
+ Offset<Vector<const T *>> CreateVectorOfStructs(
+ size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
+ T *structs = StartVectorOfStructs<T>(vector_size);
+ for (size_t i = 0; i < vector_size; i++) {
+ filler(i, structs);
+ structs++;
+ }
+ return EndVectorOfStructs<T>(vector_size);
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] f A function that takes the current iteration 0..vector_size-1,
+ /// a pointer to the struct that must be filled and the state argument.
+ /// @param[in] state Arbitrary state to pass to f.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ /// This is mostly useful when flatbuffers are generated with mutation
+ /// accessors.
+ template<typename T, typename F, typename S>
+ Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
+ S *state) {
+ T *structs = StartVectorOfStructs<T>(vector_size);
+ for (size_t i = 0; i < vector_size; i++) {
+ f(i, structs, state);
+ structs++;
+ }
+ return EndVectorOfStructs<T>(vector_size);
+ }
+
+ /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, template<typename...> class OffsetT = Offset,
+ template<typename...> class VectorT = Vector,
+ typename Alloc = std::allocator<T>>
+ OffsetT<VectorT<const T *>> CreateVectorOfStructs(
+ const std::vector<T, Alloc> &v) {
+ return CreateVectorOfStructs<T, OffsetT, VectorT>(data(v), v.size());
+ }
+
+ template<template<typename...> class VectorT = Vector64, int &..., typename T>
+ Offset64<VectorT<const T *>> CreateVectorOfStructs64(
+ const std::vector<T> &v) {
+ return CreateVectorOfStructs<T, Offset64, VectorT>(data(v), v.size());
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @param[in] pack_func Pointer to a function to convert the native struct
+ /// to the FlatBuffer struct.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(
+ const S *v, size_t len, T (*const pack_func)(const S &)) {
+ FLATBUFFERS_ASSERT(pack_func);
+ auto structs = StartVectorOfStructs<T>(len);
+ for (size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); }
+ return EndVectorOfStructs<T>(len);
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
+ size_t len) {
+ extern T Pack(const S &);
+ return CreateVectorOfNativeStructs(v, len, Pack);
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @param[in] pack_func Pointer to a function to convert the native struct
+ /// to the FlatBuffer struct.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S, typename Alloc = std::allocator<T>>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(
+ const std::vector<S, Alloc> &v, T (*const pack_func)(const S &)) {
+ return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector`.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S, typename Alloc = std::allocator<S>>
+ Offset<Vector<const T *>> CreateVectorOfNativeStructs(
+ const std::vector<S, Alloc> &v) {
+ return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ template<typename T> struct StructKeyComparator {
+ bool operator()(const T &a, const T &b) const {
+ return a.KeyCompareLessThan(&b);
+ }
+ };
+ /// @endcond
+
+ /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
+ /// in sorted order.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename Alloc = std::allocator<T>>
+ Offset<Vector<const T *>> CreateVectorOfSortedStructs(
+ std::vector<T, Alloc> *v) {
+ return CreateVectorOfSortedStructs(data(*v), v->size());
+ }
+
+ /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
+ /// `vector` in sorted order.
+ /// @tparam T The data type of the `std::vector` struct elements.
+ /// @tparam S The data type of the `std::vector` native struct elements.
+ /// @param[in] v A const reference to the `std::vector` of structs to
+ /// serialize into the buffer as a `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S, typename Alloc = std::allocator<T>>
+ Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
+ std::vector<S, Alloc> *v) {
+ return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
+ }
+
+ /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
+ /// order.
+ /// @tparam T The data type of the struct array elements.
+ /// @param[in] v A pointer to the array of type `T` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T>
+ Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
+ std::stable_sort(v, v + len, StructKeyComparator<T>());
+ return CreateVectorOfStructs(v, len);
+ }
+
+ /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
+ /// sorted order.
+ /// @tparam T The data type of the struct array elements.
+ /// @tparam S The data type of the native struct array elements.
+ /// @param[in] v A pointer to the array of type `S` to serialize into the
+ /// buffer as a `vector`.
+ /// @param[in] len The number of elements to serialize.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename S>
+ Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
+ size_t len) {
+ extern T Pack(const S &);
+ auto structs = StartVectorOfStructs<T>(len);
+ for (size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); }
+ std::stable_sort(structs, structs + len, StructKeyComparator<T>());
+ return EndVectorOfStructs<T>(len);
+ }
+
+ /// @cond FLATBUFFERS_INTERNAL
+ template<typename T> struct TableKeyComparator {
+ explicit TableKeyComparator(vector_downward<SizeT> &buf) : buf_(buf) {}
+ TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
+ bool operator()(const Offset<T> &a, const Offset<T> &b) const {
+ auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
+ auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
+ return table_a->KeyCompareLessThan(table_b);
+ }
+ vector_downward<SizeT> &buf_;
+
+ private:
+ FLATBUFFERS_DELETE_FUNC(
+ TableKeyComparator &operator=(const TableKeyComparator &other));
+ };
+ /// @endcond
+
+ /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+ /// in sorted order.
+ /// @tparam T The data type that the offset refers to.
+ /// @param[in] v An array of type `Offset<T>` that contains the `table`
+ /// offsets to store in the buffer in sorted order.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T>
+ Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
+ size_t len) {
+ std::stable_sort(v, v + len, TableKeyComparator<T>(buf_));
+ return CreateVector(v, len);
+ }
+
+ /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
+ /// in sorted order.
+ /// @tparam T The data type that the offset refers to.
+ /// @param[in] v An array of type `Offset<T>` that contains the `table`
+ /// offsets to store in the buffer in sorted order.
+ /// @return Returns a typed `Offset` into the serialized data indicating
+ /// where the vector is stored.
+ template<typename T, typename Alloc = std::allocator<T>>
+ Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
+ std::vector<Offset<T>, Alloc> *v) {
+ return CreateVectorOfSortedTables(data(*v), v->size());
+ }
+
+ /// @brief Specialized version of `CreateVector` for non-copying use cases.
+ /// Write the data any time later to the returned buffer pointer `buf`.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @param[in] elemsize The size of each element in the `vector`.
+ /// @param[out] buf A pointer to a `uint8_t` pointer that can be
+ /// written to at a later time to serialize the data into a `vector`
+ /// in the buffer.
+ uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
+ size_t alignment, uint8_t **buf) {
+ NotNested();
+ StartVector(len, elemsize, alignment);
+ buf_.make_space(len * elemsize);
+ const uoffset_t vec_start = GetSizeRelative32BitRegion();
+ auto vec_end = EndVector(len);
+ *buf = buf_.data_at(vec_start);
+ return vec_end;
+ }
+
+ FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
+ uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
+ uint8_t **buf) {
+ return CreateUninitializedVector(len, elemsize, elemsize, buf);
+ }
+
+ /// @brief Specialized version of `CreateVector` for non-copying use cases.
+ /// Write the data any time later to the returned buffer pointer `buf`.
+ /// @tparam T The data type of the data that will be stored in the buffer
+ /// as a `vector`.
+ /// @param[in] len The number of elements to store in the `vector`.
+ /// @param[out] buf A pointer to a pointer of type `T` that can be
+ /// written to at a later time to serialize the data into a `vector`
+ /// in the buffer.
+ template<typename T>
+ Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
+ AssertScalarT<T>();
+ return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
+ reinterpret_cast<uint8_t **>(buf));
+ }
+
+ template<typename T>
+ Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
+ T **buf) {
+ return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
+ reinterpret_cast<uint8_t **>(buf));
+ }
+
+ // @brief Create a vector of scalar type T given as input a vector of scalar
+ // type U, useful with e.g. pre "enum class" enums, or any existing scalar
+ // data of the wrong type.
+ template<typename T, typename U>
+ Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
+ AssertScalarT<T>();
+ AssertScalarT<U>();
+ StartVector<T>(len);
+ for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
+ return Offset<Vector<T>>(EndVector(len));
+ }
+
+ /// @brief Write a struct by itself, typically to be part of a union.
+ template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
+ NotNested();
+ Align(AlignOf<T>());
+ buf_.push_small(structobj);
+ return Offset<const T *>(
+ CalculateOffset<typename Offset<const T *>::offset_type>());
+ }
+
+ /// @brief Finish serializing a buffer by writing the root offset.
+ /// @param[in] file_identifier If a `file_identifier` is given, the buffer
+ /// will be prefixed with a standard FlatBuffers file header.
+ template<typename T>
+ void Finish(Offset<T> root, const char *file_identifier = nullptr) {
+ Finish(root.o, file_identifier, false);
+ }
+
+ /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
+ /// buffer following the size field). These buffers are NOT compatible
+ /// with standard buffers created by Finish, i.e. you can't call GetRoot
+ /// on them, you have to use GetSizePrefixedRoot instead.
+ /// All >32 bit quantities in this buffer will be aligned when the whole
+ /// size pre-fixed buffer is aligned.
+ /// These kinds of buffers are useful for creating a stream of FlatBuffers.
+ template<typename T>
+ void FinishSizePrefixed(Offset<T> root,
+ const char *file_identifier = nullptr) {
+ Finish(root.o, file_identifier, true);
+ }
+
+ void SwapBufAllocator(FlatBufferBuilderImpl &other) {
+ buf_.swap_allocator(other.buf_);
+ }
+
+ /// @brief The length of a FlatBuffer file header.
+ static const size_t kFileIdentifierLength =
+ ::flatbuffers::kFileIdentifierLength;
+
+ protected:
+ // You shouldn't really be copying instances of this class.
+ FlatBufferBuilderImpl(const FlatBufferBuilderImpl &);
+ FlatBufferBuilderImpl &operator=(const FlatBufferBuilderImpl &);
+
+ void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
+ NotNested();
+ buf_.clear_scratch();
+
+ const size_t prefix_size = size_prefix ? sizeof(SizeT) : 0;
+ // Make sure we track the alignment of the size prefix.
+ TrackMinAlign(prefix_size);
+
+ const size_t root_offset_size = sizeof(uoffset_t);
+ const size_t file_id_size = file_identifier ? kFileIdentifierLength : 0;
+
+ // This will cause the whole buffer to be aligned.
+ PreAlign(prefix_size + root_offset_size + file_id_size, minalign_);
+
+ if (file_identifier) {
+ FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
+ PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
+ kFileIdentifierLength);
+ }
+ PushElement(ReferTo(root)); // Location of root.
+ if (size_prefix) { PushElement(GetSize()); }
+ finished = true;
+ }
+
+ struct FieldLoc {
+ uoffset_t off;
+ voffset_t id;
+ };
+
+ vector_downward<SizeT> buf_;
+
+ // Accumulating offsets of table members while it is being built.
+ // We store these in the scratch pad of buf_, after the vtable offsets.
+ uoffset_t num_field_loc;
+ // Track how much of the vtable is in use, so we can output the most compact
+ // possible vtable.
+ voffset_t max_voffset_;
+
+ // This is the length of the 64-bit region of the buffer. The buffer supports
+ // 64-bit offsets by forcing serialization of those elements in the "tail"
+ // region of the buffer (i.e. "64-bit region"). To properly keep track of
+ // offsets that are referenced from the tail of the buffer to not overflow
+ // their size (e.g. Offset is a uint32_t type), the boundary of the 32-/64-bit
+ // regions must be tracked.
+ //
+ // [ Complete FlatBuffer ]
+ // [32-bit region][64-bit region]
+ // ^ ^
+ // | Tail of the buffer.
+ // |
+ // Tail of the 32-bit region of the buffer.
+ //
+ // This keeps track of the size of the 64-bit region so that the tail of the
+ // 32-bit region can be calculated as `GetSize() - length_of_64_bit_region_`.
+ //
+ // This will remain 0 if no 64-bit offset types are added to the buffer.
+ size_t length_of_64_bit_region_;
+
+ // When true, 64-bit offsets can still be added to the builder. When false,
+ // only 32-bit offsets can be added, and attempts to add a 64-bit offset will
+ // raise an assertion. This is typically a compile-time error in ordering the
+ // serialization of 64-bit offset fields not at the tail of the buffer.
+
+ // Ensure objects are not nested.
+ bool nested;
+
+ // Ensure the buffer is finished before it is being accessed.
+ bool finished;
+
+ size_t minalign_;
+
+ bool force_defaults_; // Serialize values equal to their defaults anyway.
+
+ bool dedup_vtables_;
+
+ struct StringOffsetCompare {
+ explicit StringOffsetCompare(const vector_downward<SizeT> &buf)
+ : buf_(&buf) {}
+ bool operator()(const Offset<String> &a, const Offset<String> &b) const {
+ auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
+ auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
+ return StringLessThan(stra->data(), stra->size(), strb->data(),
+ strb->size());
+ }
+ const vector_downward<SizeT> *buf_;
+ };
+
+ // For use with CreateSharedString. Instantiated on first use only.
+ typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
+ StringOffsetMap *string_pool;
+
+ private:
+ void CanAddOffset64() {
+ // If you hit this assertion, you are attempting to add a 64-bit offset to
+ // a 32-bit only builder. This is because the builder has overloads that
+ // differ only on the offset size returned: e.g.:
+ //
+ // FlatBufferBuilder builder;
+ // Offset64<String> string_offset = builder.CreateString<Offset64>();
+ //
+ // Either use a 64-bit aware builder, or don't try to create an Offset64
+ // return type.
+ //
+ // TODO(derekbailey): we can probably do more enable_if to avoid this
+ // looking like its possible to the user.
+ static_assert(Is64Aware, "cannot add 64-bit offset to a 32-bit builder");
+
+ // If you hit this assertion, you are attempting to add an 64-bit offset
+ // item after already serializing a 32-bit item. All 64-bit offsets have to
+ // added to the tail of the buffer before any 32-bit items can be added.
+ // Otherwise some items might not be addressable due to the maximum range of
+ // the 32-bit offset.
+ FLATBUFFERS_ASSERT(GetSize() == length_of_64_bit_region_);
+ }
+
+ /// @brief Store a string in the buffer, which can contain any binary data.
+ /// @param[in] str A const char pointer to the data to be stored as a string.
+ /// @param[in] len The number of bytes that should be stored from `str`.
+ /// @return Returns the offset in the buffer where the string starts.
+ void CreateStringImpl(const char *str, size_t len) {
+ NotNested();
+ PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
+ buf_.fill(1);
+ PushBytes(reinterpret_cast<const uint8_t *>(str), len);
+ PushElement(static_cast<uoffset_t>(len));
+ }
+
+ // Allocates space for a vector of structures.
+ // Must be completed with EndVectorOfStructs().
+ template<typename T, template<typename> class OffsetT = Offset>
+ T *StartVectorOfStructs(size_t vector_size) {
+ StartVector<OffsetT>(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T),
+ AlignOf<T>());
+ return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
+ }
+
+ // End the vector of structures in the flatbuffers.
+ // Vector should have previously be started with StartVectorOfStructs().
+ template<typename T, template<typename> class OffsetT = Offset>
+ OffsetT<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
+ return OffsetT<Vector<const T *>>(
+ EndVector<typename Vector<const T *>::size_type,
+ typename OffsetT<Vector<const T *>>::offset_type>(
+ vector_size));
+ }
+
+ template<typename T>
+ typename std::enable_if<std::is_same<T, uoffset_t>::value, T>::type
+ CalculateOffset() {
+ // Default to the end of the 32-bit region. This may or may not be the end
+ // of the buffer, depending on if any 64-bit offsets have been added.
+ return GetSizeRelative32BitRegion();
+ }
+
+ // Specializations to handle the 64-bit CalculateOffset, which is relative to
+ // end of the buffer.
+ template<typename T>
+ typename std::enable_if<std::is_same<T, uoffset64_t>::value, T>::type
+ CalculateOffset() {
+ // This should never be compiled in when not using a 64-bit builder.
+ static_assert(Is64Aware, "invalid 64-bit offset in 32-bit builder");
+
+ // Store how big the 64-bit region of the buffer is, so we can determine
+ // where the 32/64 bit boundary is.
+ length_of_64_bit_region_ = GetSize();
+
+ return length_of_64_bit_region_;
+ }
+};
+/// @}
+
+// Hack to `FlatBufferBuilder` mean `FlatBufferBuilder<false>` or
+// `FlatBufferBuilder<>`, where the template < > syntax is required.
+typedef FlatBufferBuilderImpl<false> FlatBufferBuilder;
+typedef FlatBufferBuilderImpl<true> FlatBufferBuilder64;
+
+// These are external due to GCC not allowing them in the class.
+// See: https://stackoverflow.com/q/8061456/868247
+template<>
+template<>
+inline Offset64<String> FlatBufferBuilder64::CreateString(const char *str,
+ size_t len) {
+ CanAddOffset64();
+ CreateStringImpl(str, len);
+ return Offset64<String>(
+ CalculateOffset<typename Offset64<String>::offset_type>());
+}
+
+// Used to distinguish from real Offsets.
+template<typename T = void> struct EmptyOffset {};
+
+// TODO(derekbailey): it would be nice to combine these two methods.
+template<>
+template<>
+inline void FlatBufferBuilder64::StartVector<Offset64, uint32_t>(
+ size_t len, size_t elemsize, size_t alignment) {
+ CanAddOffset64();
+ StartVector<EmptyOffset, uint32_t>(len, elemsize, alignment);
+}
+
+template<>
+template<>
+inline void FlatBufferBuilder64::StartVector<Offset64, uint64_t>(
+ size_t len, size_t elemsize, size_t alignment) {
+ CanAddOffset64();
+ StartVector<EmptyOffset, uint64_t>(len, elemsize, alignment);
+}
+
+/// Helpers to get a typed pointer to objects that are currently being built.
+/// @warning Creating new objects will lead to reallocations and invalidates
+/// the pointer!
+template<typename T>
+T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
+ return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
+ offset.o);
+}
+
+template<typename T>
+const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
+ return GetMutableTemporaryPointer<T>(fbb, offset);
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_FLATBUFFER_BUILDER_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h
index 20935307a6..acf1e2c0ea 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h
@@ -17,2686 +17,25 @@
#ifndef FLATBUFFERS_H_
#define FLATBUFFERS_H_
+#include <algorithm>
+
+// TODO: These includes are for mitigating the pains of users editing their
+// source because they relied on flatbuffers.h to include everything for them.
+#include "array.h"
#include "base.h"
+#include "buffer.h"
+#include "buffer_ref.h"
+#include "detached_buffer.h"
+#include "flatbuffer_builder.h"
#include "stl_emulation.h"
-
-#ifndef FLATBUFFERS_CPP98_STL
-# include <functional>
-#endif
-
-#if defined(FLATBUFFERS_NAN_DEFAULTS)
-# include <cmath>
-#endif
+#include "string.h"
+#include "struct.h"
+#include "table.h"
+#include "vector.h"
+#include "vector_downward.h"
+#include "verifier.h"
namespace flatbuffers {
-// Generic 'operator==' with conditional specialisations.
-// T e - new value of a scalar field.
-// T def - default of scalar (is known at compile-time).
-template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
-
-#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
- defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
-// Like `operator==(e, def)` with weak NaN if T=(float|double).
-template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
- return (e == def) || ((def != def) && (e != e));
-}
-template<> inline bool IsTheSameAs<float>(float e, float def) {
- return IsFloatTheSameAs(e, def);
-}
-template<> inline bool IsTheSameAs<double>(double e, double def) {
- return IsFloatTheSameAs(e, def);
-}
-#endif
-
-// Check 'v' is out of closed range [low; high].
-// Workaround for GCC warning [-Werror=type-limits]:
-// comparison is always true due to limited range of data type.
-template<typename T>
-inline bool IsOutRange(const T &v, const T &low, const T &high) {
- return (v < low) || (high < v);
-}
-
-// Check 'v' is in closed range [low; high].
-template<typename T>
-inline bool IsInRange(const T &v, const T &low, const T &high) {
- return !IsOutRange(v, low, high);
-}
-
-// Wrapper for uoffset_t to allow safe template specialization.
-// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
-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); }
- bool IsNull() const { return !o; }
-};
-
-inline void EndianCheck() {
- int endiantest = 1;
- // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
- FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
- FLATBUFFERS_LITTLEENDIAN);
- (void)endiantest;
-}
-
-template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
- // clang-format off
- #ifdef _MSC_VER
- return __alignof(T);
- #else
- #ifndef alignof
- return __alignof__(T);
- #else
- return alignof(T);
- #endif
- #endif
- // clang-format on
-}
-
-// 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);
- static return_type Read(const uint8_t *p, uoffset_t i) {
- return EndianScalar((reinterpret_cast<const T *>(p))[i]);
- }
-};
-template<typename T> struct IndirectHelper<Offset<T>> {
- typedef const T *return_type;
- typedef T *mutable_return_type;
- static const size_t element_stride = sizeof(uoffset_t);
- static return_type Read(const uint8_t *p, uoffset_t i) {
- p += i * sizeof(uoffset_t);
- return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
- }
-};
-template<typename T> struct IndirectHelper<const T *> {
- typedef const T *return_type;
- typedef T *mutable_return_type;
- static const size_t element_stride = sizeof(T);
- static return_type Read(const uint8_t *p, uoffset_t i) {
- return reinterpret_cast<const T *>(p + i * sizeof(T));
- }
-};
-
-// An STL compatible iterator implementation for Vector below, effectively
-// calling Get() for every element.
-template<typename T, typename IT> struct VectorIterator {
- typedef std::random_access_iterator_tag iterator_category;
- typedef IT value_type;
- typedef ptrdiff_t difference_type;
- typedef IT *pointer;
- typedef IT &reference;
-
- VectorIterator(const uint8_t *data, uoffset_t i)
- : data_(data + IndirectHelper<T>::element_stride * i) {}
- VectorIterator(const VectorIterator &other) : data_(other.data_) {}
- VectorIterator() : data_(nullptr) {}
-
- VectorIterator &operator=(const VectorIterator &other) {
- data_ = other.data_;
- return *this;
- }
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- VectorIterator &operator=(VectorIterator &&other) {
- data_ = other.data_;
- return *this;
- }
- #endif // !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- bool operator==(const VectorIterator &other) const {
- return data_ == other.data_;
- }
-
- bool operator<(const VectorIterator &other) const {
- return data_ < other.data_;
- }
-
- bool operator!=(const VectorIterator &other) const {
- return data_ != other.data_;
- }
-
- difference_type operator-(const VectorIterator &other) const {
- return (data_ - other.data_) / IndirectHelper<T>::element_stride;
- }
-
- // Note: return type is incompatible with the standard
- // `reference operator*()`.
- IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
-
- // Note: return type is incompatible with the standard
- // `pointer operator->()`.
- IT 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) const {
- 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) const {
- return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
- 0);
- }
-
- VectorIterator &operator-=(const uoffset_t &offset) {
- data_ -= offset * IndirectHelper<T>::element_stride;
- return *this;
- }
-
- private:
- const uint8_t *data_;
-};
-
-template<typename Iterator>
-struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
- explicit VectorReverseIterator(Iterator iter)
- : std::reverse_iterator<Iterator>(iter) {}
-
- // Note: return type is incompatible with the standard
- // `reference operator*()`.
- typename Iterator::value_type operator*() const {
- auto tmp = std::reverse_iterator<Iterator>::current;
- return *--tmp;
- }
-
- // Note: return type is incompatible with the standard
- // `pointer operator->()`.
- typename Iterator::value_type operator->() const {
- auto tmp = std::reverse_iterator<Iterator>::current;
- return *--tmp;
- }
-};
-
-struct String;
-
-// This is used as a helper type for accessing vectors.
-// Vector::data() assumes the vector elements start after the length field.
-template<typename T> class Vector {
- public:
- typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
- iterator;
- typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
- const_iterator;
- typedef VectorReverseIterator<iterator> reverse_iterator;
- typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
-
- uoffset_t size() const { return EndianScalar(length_); }
-
- // Deprecated: use size(). Here for backwards compatibility.
- FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
- uoffset_t Length() const { return size(); }
-
- typedef typename IndirectHelper<T>::return_type return_type;
- typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
- typedef return_type value_type;
-
- return_type Get(uoffset_t i) const {
- FLATBUFFERS_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));
- }
-
- // If this a vector of unions, this does the cast for you. There's no check
- // to make sure this is the right type!
- template<typename U> const U *GetAs(uoffset_t i) const {
- return reinterpret_cast<const U *>(Get(i));
- }
-
- // If this a vector of unions, this does the cast for you. There's no check
- // to make sure this is actually a string!
- const String *GetAsString(uoffset_t i) const {
- return reinterpret_cast<const String *>(Get(i));
- }
-
- const void *GetStructFromOffset(size_t o) const {
- return reinterpret_cast<const void *>(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()); }
-
- reverse_iterator rbegin() { return reverse_iterator(end()); }
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
-
- reverse_iterator rend() { return reverse_iterator(begin()); }
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
-
- const_iterator cbegin() const { return begin(); }
-
- const_iterator cend() const { return end(); }
-
- const_reverse_iterator crbegin() const { return rbegin(); }
-
- const_reverse_iterator crend() const { return rend(); }
-
- // Change elements if you have a non-const pointer to this object.
- // Scalars only. See reflection.h, and the documentation.
- void Mutate(uoffset_t i, const T &val) {
- FLATBUFFERS_ASSERT(i < size());
- WriteScalar(data() + i, val);
- }
-
- // Change an element of a vector of tables (or strings).
- // "val" points to the new table/string, as you can obtain from
- // e.g. reflection::AddFlatBuffer().
- void MutateOffset(uoffset_t i, const uint8_t *val) {
- FLATBUFFERS_ASSERT(i < size());
- static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
- WriteScalar(data() + i,
- static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
- }
-
- // Get a mutable pointer to tables/strings inside this vector.
- mutable_return_type GetMutableObject(uoffset_t i) const {
- FLATBUFFERS_ASSERT(i < size());
- return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
- }
-
- // The raw data in little endian format. Use with care.
- const uint8_t *Data() const {
- return reinterpret_cast<const uint8_t *>(&length_ + 1);
- }
-
- uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
-
- // Similarly, but typed, much like std::vector::data
- const T *data() const { return reinterpret_cast<const T *>(Data()); }
- T *data() { return reinterpret_cast<T *>(Data()); }
-
- template<typename K> return_type LookupByKey(K key) const {
- void *search_result = std::bsearch(
- &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
-
- if (!search_result) {
- return nullptr; // Key not found.
- }
-
- const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
-
- return IndirectHelper<T>::Read(element, 0);
- }
-
- protected:
- // This class is only used to access pre-existing data. Don't ever
- // try to construct these manually.
- Vector();
-
- uoffset_t length_;
-
- private:
- // This class is a pointer. Copying will therefore create an invalid object.
- // Private and unimplemented copy constructor.
- Vector(const Vector &);
- Vector &operator=(const Vector &);
-
- template<typename K> static int KeyCompare(const void *ap, const void *bp) {
- const K *key = reinterpret_cast<const K *>(ap);
- const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
- auto table = IndirectHelper<T>::Read(data, 0);
-
- // std::bsearch compares with the operands transposed, so we negate the
- // result here.
- return -table->KeyCompareWithValue(*key);
- }
-};
-
-// 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).
-class VectorOfAny {
- public:
- uoffset_t size() const { return EndianScalar(length_); }
-
- const uint8_t *Data() const {
- return reinterpret_cast<const uint8_t *>(&length_ + 1);
- }
- uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
-
- protected:
- VectorOfAny();
-
- uoffset_t length_;
-
- private:
- VectorOfAny(const VectorOfAny &);
- VectorOfAny &operator=(const VectorOfAny &);
-};
-
-#ifndef FLATBUFFERS_CPP98_STL
-template<typename T, typename U>
-Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
- static_assert(std::is_base_of<T, U>::value, "Unrelated types");
- return reinterpret_cast<Vector<Offset<T>> *>(ptr);
-}
-
-template<typename T, typename U>
-const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
- static_assert(std::is_base_of<T, U>::value, "Unrelated types");
- return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
-}
-#endif
-
-// Convenient helper function to get the length of any vector, regardless
-// of whether it is null or not (the field is not set).
-template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
- return v ? v->size() : 0;
-}
-
-// This is used as a helper type for accessing arrays.
-template<typename T, uint16_t length> class Array {
- typedef
- typename flatbuffers::integral_constant<bool,
- flatbuffers::is_scalar<T>::value>
- scalar_tag;
- typedef
- typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
- IndirectHelperType;
-
- public:
- typedef uint16_t size_type;
- typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
- typedef VectorIterator<T, return_type> const_iterator;
- typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
-
- FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
-
- return_type Get(uoffset_t i) const {
- FLATBUFFERS_ASSERT(i < size());
- return IndirectHelper<IndirectHelperType>::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_iterator begin() const { return const_iterator(Data(), 0); }
- const_iterator end() const { return const_iterator(Data(), size()); }
-
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
-
- const_iterator cbegin() const { return begin(); }
- const_iterator cend() const { return end(); }
-
- const_reverse_iterator crbegin() const { return rbegin(); }
- const_reverse_iterator crend() const { return rend(); }
-
- // Get a mutable pointer to elements inside this array.
- // This method used to mutate arrays of structs followed by a @p Mutate
- // operation. For primitive types use @p Mutate directly.
- // @warning Assignments and reads to/from the dereferenced pointer are not
- // automatically converted to the correct endianness.
- typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
- GetMutablePointer(uoffset_t i) const {
- FLATBUFFERS_ASSERT(i < size());
- return const_cast<T *>(&data()[i]);
- }
-
- // Change elements if you have a non-const pointer to this object.
- void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
-
- // The raw data in little endian format. Use with care.
- const uint8_t *Data() const { return data_; }
-
- uint8_t *Data() { return data_; }
-
- // Similarly, but typed, much like std::vector::data
- const T *data() const { return reinterpret_cast<const T *>(Data()); }
- T *data() { return reinterpret_cast<T *>(Data()); }
-
- // Copy data from a span with endian conversion.
- // If this Array and the span overlap, the behavior is undefined.
- void CopyFromSpan(flatbuffers::span<const T, length> src) {
- const auto p1 = reinterpret_cast<const uint8_t *>(src.data());
- const auto p2 = Data();
- FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
- !(p2 >= p1 && p2 < (p1 + length)));
- (void)p1;
- (void)p2;
-
- CopyFromSpanImpl(
- flatbuffers::integral_constant < bool,
- !scalar_tag::value || sizeof(T) == 1 || FLATBUFFERS_LITTLEENDIAN > (),
- src);
- }
-
- protected:
- void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i,
- const T &val) {
- FLATBUFFERS_ASSERT(i < size());
- WriteScalar(data() + i, val);
- }
-
- void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i,
- const T &val) {
- *(GetMutablePointer(i)) = val;
- }
-
- void CopyFromSpanImpl(flatbuffers::integral_constant<bool, true>,
- flatbuffers::span<const T, length> src) {
- // Use std::memcpy() instead of std::copy() to avoid preformance degradation
- // due to aliasing if T is char or unsigned char.
- // The size is known at compile time, so memcpy would be inlined.
- std::memcpy(data(), src.data(), length * sizeof(T));
- }
-
- // Copy data from flatbuffers::span with endian conversion.
- void CopyFromSpanImpl(flatbuffers::integral_constant<bool, false>,
- flatbuffers::span<const T, length> src) {
- for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
- }
-
- // This class is only used to access pre-existing data. Don't ever
- // try to construct these manually.
- // 'constexpr' allows us to use 'size()' at compile time.
- // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
- // a constructor.
-#if defined(__cpp_constexpr)
- constexpr Array();
-#else
- Array();
-#endif
-
- uint8_t data_[length * sizeof(T)];
-
- private:
- // This class is a pointer. Copying will therefore create an invalid object.
- // Private and unimplemented copy constructor.
- Array(const Array &);
- Array &operator=(const Array &);
-};
-
-// Specialization for Array[struct] with access using Offset<void> pointer.
-// This specialization used by idl_gen_text.cpp.
-template<typename T, uint16_t length> class Array<Offset<T>, length> {
- static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
-
- public:
- typedef const void *return_type;
-
- const uint8_t *Data() const { return data_; }
-
- // Make idl_gen_text.cpp::PrintContainer happy.
- return_type operator[](uoffset_t) const {
- FLATBUFFERS_ASSERT(false);
- return nullptr;
- }
-
- private:
- // This class is only used to access pre-existing data.
- Array();
- Array(const Array &);
- Array &operator=(const Array &);
-
- uint8_t data_[1];
-};
-
-// Cast a raw T[length] to a raw flatbuffers::Array<T, length>
-// without endian conversion. Use with care.
-template<typename T, uint16_t length>
-Array<T, length> &CastToArray(T (&arr)[length]) {
- return *reinterpret_cast<Array<T, length> *>(arr);
-}
-
-template<typename T, uint16_t length>
-const Array<T, length> &CastToArray(const T (&arr)[length]) {
- return *reinterpret_cast<const Array<T, length> *>(arr);
-}
-
-template<typename E, typename T, uint16_t length>
-Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
- static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
- return *reinterpret_cast<Array<E, length> *>(arr);
-}
-
-template<typename E, typename T, uint16_t length>
-const Array<E, length> &CastToArrayOfEnum(const T (&arr)[length]) {
- static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
- return *reinterpret_cast<const Array<E, length> *>(arr);
-}
-
-// Lexicographically compare two strings (possibly containing nulls), and
-// return true if the first is less than the second.
-static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
- const char *b_data, uoffset_t b_size) {
- const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
- return cmp == 0 ? a_size < b_size : cmp < 0;
-}
-
-struct String : public Vector<char> {
- const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
- std::string str() const { return std::string(c_str(), size()); }
-
- // clang-format off
- #ifdef FLATBUFFERS_HAS_STRING_VIEW
- flatbuffers::string_view string_view() const {
- return flatbuffers::string_view(c_str(), size());
- }
- #endif // FLATBUFFERS_HAS_STRING_VIEW
- // clang-format on
-
- bool operator<(const String &o) const {
- return StringLessThan(this->data(), this->size(), o.data(), o.size());
- }
-};
-
-// Convenience function to get std::string from a String returning an empty
-// string on null pointer.
-static inline std::string GetString(const String *str) {
- return str ? str->str() : "";
-}
-
-// Convenience function to get char* from a String returning an empty string on
-// null pointer.
-static inline const char *GetCstring(const String *str) {
- return str ? str->c_str() : "";
-}
-
-#ifdef FLATBUFFERS_HAS_STRING_VIEW
-// Convenience function to get string_view from a String returning an empty
-// string_view on null pointer.
-static inline flatbuffers::string_view GetStringView(const String *str) {
- return str ? str->string_view() : flatbuffers::string_view();
-}
-#endif // FLATBUFFERS_HAS_STRING_VIEW
-
-// Allocator interface. This is flatbuffers-specific and meant only for
-// `vector_downward` usage.
-class Allocator {
- public:
- virtual ~Allocator() {}
-
- // Allocate `size` bytes of memory.
- virtual uint8_t *allocate(size_t size) = 0;
-
- // Deallocate `size` bytes of memory at `p` allocated by this allocator.
- virtual void deallocate(uint8_t *p, size_t size) = 0;
-
- // Reallocate `new_size` bytes of memory, replacing the old region of size
- // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
- // and is intended specifcally for `vector_downward` use.
- // `in_use_back` and `in_use_front` indicate how much of `old_size` is
- // actually in use at each end, and needs to be copied.
- virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
- size_t new_size, size_t in_use_back,
- size_t in_use_front) {
- FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
- uint8_t *new_p = allocate(new_size);
- memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
- in_use_front);
- deallocate(old_p, old_size);
- return new_p;
- }
-
- protected:
- // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
- // to `new_p` of `new_size`. Only memory of size `in_use_front` and
- // `in_use_back` will be copied from the front and back of the old memory
- // allocation.
- void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
- size_t new_size, size_t in_use_back,
- size_t in_use_front) {
- memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
- in_use_back);
- memcpy(new_p, old_p, in_use_front);
- }
-};
-
-// DefaultAllocator uses new/delete to allocate memory regions
-class DefaultAllocator : public Allocator {
- public:
- uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
- return new uint8_t[size];
- }
-
- void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
-
- static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
-};
-
-// These functions allow for a null allocator to mean use the default allocator,
-// as used by DetachedBuffer and vector_downward below.
-// This is to avoid having a statically or dynamically allocated default
-// allocator, or having to move it between the classes that may own it.
-inline uint8_t *Allocate(Allocator *allocator, size_t size) {
- return allocator ? allocator->allocate(size)
- : DefaultAllocator().allocate(size);
-}
-
-inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
- if (allocator)
- allocator->deallocate(p, size);
- else
- DefaultAllocator().deallocate(p, size);
-}
-
-inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
- size_t old_size, size_t new_size,
- size_t in_use_back, size_t in_use_front) {
- return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
- in_use_back, in_use_front)
- : DefaultAllocator().reallocate_downward(
- old_p, old_size, new_size, in_use_back, in_use_front);
-}
-
-// DetachedBuffer is a finished flatbuffer memory region, detached from its
-// builder. The original memory region and allocator are also stored so that
-// the DetachedBuffer can manage the memory lifetime.
-class DetachedBuffer {
- public:
- DetachedBuffer()
- : allocator_(nullptr),
- own_allocator_(false),
- buf_(nullptr),
- reserved_(0),
- cur_(nullptr),
- size_(0) {}
-
- DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
- size_t reserved, uint8_t *cur, size_t sz)
- : allocator_(allocator),
- own_allocator_(own_allocator),
- buf_(buf),
- reserved_(reserved),
- cur_(cur),
- size_(sz) {}
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- DetachedBuffer(DetachedBuffer &&other)
- : allocator_(other.allocator_),
- own_allocator_(other.own_allocator_),
- buf_(other.buf_),
- reserved_(other.reserved_),
- cur_(other.cur_),
- size_(other.size_) {
- other.reset();
- }
- // clang-format off
- #endif // !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- DetachedBuffer &operator=(DetachedBuffer &&other) {
- if (this == &other) return *this;
-
- destroy();
-
- allocator_ = other.allocator_;
- own_allocator_ = other.own_allocator_;
- buf_ = other.buf_;
- reserved_ = other.reserved_;
- cur_ = other.cur_;
- size_ = other.size_;
-
- other.reset();
-
- return *this;
- }
- // clang-format off
- #endif // !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- ~DetachedBuffer() { destroy(); }
-
- const uint8_t *data() const { return cur_; }
-
- uint8_t *data() { return cur_; }
-
- size_t size() const { return size_; }
-
- // clang-format off
- #if 0 // disabled for now due to the ordering of classes in this header
- template <class T>
- bool Verify() const {
- Verifier verifier(data(), size());
- return verifier.Verify<T>(nullptr);
- }
-
- template <class T>
- const T* GetRoot() const {
- return flatbuffers::GetRoot<T>(data());
- }
-
- template <class T>
- T* GetRoot() {
- return flatbuffers::GetRoot<T>(data());
- }
- #endif
- // clang-format on
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- // These may change access mode, leave these at end of public section
- FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other));
- FLATBUFFERS_DELETE_FUNC(
- DetachedBuffer &operator=(const DetachedBuffer &other));
- // clang-format off
- #endif // !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- protected:
- Allocator *allocator_;
- bool own_allocator_;
- uint8_t *buf_;
- size_t reserved_;
- uint8_t *cur_;
- size_t size_;
-
- inline void destroy() {
- if (buf_) Deallocate(allocator_, buf_, reserved_);
- if (own_allocator_ && allocator_) { delete allocator_; }
- reset();
- }
-
- inline void reset() {
- allocator_ = nullptr;
- own_allocator_ = false;
- buf_ = nullptr;
- reserved_ = 0;
- cur_ = nullptr;
- size_ = 0;
- }
-};
-
-// This is a minimal replication of std::vector<uint8_t> functionality,
-// except growing from higher to lower addresses. i.e push_back() inserts data
-// in the lowest address in the vector.
-// Since this vector leaves the lower part unused, we support a "scratch-pad"
-// that can be stored there for temporary data, to share the allocated space.
-// Essentially, this supports 2 std::vectors in a single buffer.
-class vector_downward {
- public:
- explicit vector_downward(size_t initial_size, Allocator *allocator,
- bool own_allocator, size_t buffer_minalign)
- : allocator_(allocator),
- own_allocator_(own_allocator),
- initial_size_(initial_size),
- buffer_minalign_(buffer_minalign),
- reserved_(0),
- buf_(nullptr),
- cur_(nullptr),
- scratch_(nullptr) {}
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- vector_downward(vector_downward &&other)
- #else
- vector_downward(vector_downward &other)
- #endif // defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- : allocator_(other.allocator_),
- own_allocator_(other.own_allocator_),
- initial_size_(other.initial_size_),
- buffer_minalign_(other.buffer_minalign_),
- reserved_(other.reserved_),
- buf_(other.buf_),
- cur_(other.cur_),
- scratch_(other.scratch_) {
- // No change in other.allocator_
- // No change in other.initial_size_
- // No change in other.buffer_minalign_
- other.own_allocator_ = false;
- other.reserved_ = 0;
- other.buf_ = nullptr;
- other.cur_ = nullptr;
- other.scratch_ = nullptr;
- }
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- vector_downward &operator=(vector_downward &&other) {
- // Move construct a temporary and swap idiom
- vector_downward temp(std::move(other));
- swap(temp);
- return *this;
- }
- // clang-format off
- #endif // defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- ~vector_downward() {
- clear_buffer();
- clear_allocator();
- }
-
- void reset() {
- clear_buffer();
- clear();
- }
-
- void clear() {
- if (buf_) {
- cur_ = buf_ + reserved_;
- } else {
- reserved_ = 0;
- cur_ = nullptr;
- }
- clear_scratch();
- }
-
- void clear_scratch() { scratch_ = buf_; }
-
- void clear_allocator() {
- if (own_allocator_ && allocator_) { delete allocator_; }
- allocator_ = nullptr;
- own_allocator_ = false;
- }
-
- void clear_buffer() {
- if (buf_) Deallocate(allocator_, buf_, reserved_);
- buf_ = nullptr;
- }
-
- // Relinquish the pointer to the caller.
- uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
- auto *buf = buf_;
- allocated_bytes = reserved_;
- offset = static_cast<size_t>(cur_ - buf_);
-
- // release_raw only relinquishes the buffer ownership.
- // Does not deallocate or reset the allocator. Destructor will do that.
- buf_ = nullptr;
- clear();
- return buf;
- }
-
- // Relinquish the pointer to the caller.
- DetachedBuffer release() {
- // allocator ownership (if any) is transferred to DetachedBuffer.
- DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
- size());
- if (own_allocator_) {
- allocator_ = nullptr;
- own_allocator_ = false;
- }
- buf_ = nullptr;
- clear();
- return fb;
- }
-
- size_t ensure_space(size_t len) {
- FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
- if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
- // Beyond this, signed offsets may not have enough range:
- // (FlatBuffers > 2GB not supported).
- FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
- return len;
- }
-
- inline uint8_t *make_space(size_t len) {
- size_t space = ensure_space(len);
- cur_ -= space;
- return cur_;
- }
-
- // Returns nullptr if using the DefaultAllocator.
- Allocator *get_custom_allocator() { return allocator_; }
-
- uoffset_t size() const {
- return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
- }
-
- uoffset_t scratch_size() const {
- return static_cast<uoffset_t>(scratch_ - buf_);
- }
-
- size_t capacity() const { return reserved_; }
-
- uint8_t *data() const {
- FLATBUFFERS_ASSERT(cur_);
- return cur_;
- }
-
- uint8_t *scratch_data() const {
- FLATBUFFERS_ASSERT(buf_);
- return buf_;
- }
-
- uint8_t *scratch_end() const {
- FLATBUFFERS_ASSERT(scratch_);
- return scratch_;
- }
-
- uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
-
- void push(const uint8_t *bytes, size_t num) {
- if (num > 0) { memcpy(make_space(num), bytes, num); }
- }
-
- // Specialized version of push() that avoids memcpy call for small data.
- template<typename T> void push_small(const T &little_endian_t) {
- make_space(sizeof(T));
- *reinterpret_cast<T *>(cur_) = little_endian_t;
- }
-
- template<typename T> void scratch_push_small(const T &t) {
- ensure_space(sizeof(T));
- *reinterpret_cast<T *>(scratch_) = t;
- scratch_ += sizeof(T);
- }
-
- // fill() is most frequently called with small byte counts (<= 4),
- // which is why we're using loops rather than calling memset.
- void fill(size_t zero_pad_bytes) {
- make_space(zero_pad_bytes);
- for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
- }
-
- // Version for when we know the size is larger.
- // Precondition: zero_pad_bytes > 0
- void fill_big(size_t zero_pad_bytes) {
- memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
- }
-
- void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
- void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
-
- void swap(vector_downward &other) {
- using std::swap;
- swap(allocator_, other.allocator_);
- swap(own_allocator_, other.own_allocator_);
- swap(initial_size_, other.initial_size_);
- swap(buffer_minalign_, other.buffer_minalign_);
- swap(reserved_, other.reserved_);
- swap(buf_, other.buf_);
- swap(cur_, other.cur_);
- swap(scratch_, other.scratch_);
- }
-
- void swap_allocator(vector_downward &other) {
- using std::swap;
- swap(allocator_, other.allocator_);
- swap(own_allocator_, other.own_allocator_);
- }
-
- private:
- // You shouldn't really be copying instances of this class.
- FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &));
- FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &));
-
- Allocator *allocator_;
- bool own_allocator_;
- size_t initial_size_;
- size_t buffer_minalign_;
- size_t reserved_;
- uint8_t *buf_;
- uint8_t *cur_; // Points at location between empty (below) and used (above).
- uint8_t *scratch_; // Points to the end of the scratchpad in use.
-
- void reallocate(size_t len) {
- auto old_reserved = reserved_;
- auto old_size = size();
- auto old_scratch_size = scratch_size();
- reserved_ +=
- (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
- reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
- if (buf_) {
- buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
- old_size, old_scratch_size);
- } else {
- buf_ = Allocate(allocator_, reserved_);
- }
- cur_ = buf_ + reserved_ - old_size;
- scratch_ = buf_ + old_scratch_size;
- }
-};
-
-// 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));
-}
-
-template<typename T, typename Alloc>
-const T *data(const std::vector<T, Alloc> &v) {
- // Eventually the returned pointer gets passed down to memcpy, so
- // we need it to be non-null to avoid undefined behavior.
- static uint8_t t;
- return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
-}
-template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
- // Eventually the returned pointer gets passed down to memcpy, so
- // we need it to be non-null to avoid undefined behavior.
- static uint8_t t;
- return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
-}
-
-/// @endcond
-
-/// @addtogroup flatbuffers_cpp_api
-/// @{
-/// @class FlatBufferBuilder
-/// @brief Helper class to hold data needed in creation of a FlatBuffer.
-/// To serialize data, you typically call one of the `Create*()` functions in
-/// the generated code, which in turn call a sequence of `StartTable`/
-/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
-/// `CreateVector` functions. Do this is depth-first order to build up a tree to
-/// the root. `Finish()` wraps up the buffer ready for transport.
-class FlatBufferBuilder {
- public:
- /// @brief Default constructor for FlatBufferBuilder.
- /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
- /// to `1024`.
- /// @param[in] allocator An `Allocator` to use. If null will use
- /// `DefaultAllocator`.
- /// @param[in] own_allocator Whether the builder/vector should own the
- /// allocator. Defaults to / `false`.
- /// @param[in] buffer_minalign Force the buffer to be aligned to the given
- /// minimum alignment upon reallocation. Only needed if you intend to store
- /// types with custom alignment AND you wish to read the buffer in-place
- /// directly after creation.
- explicit FlatBufferBuilder(
- size_t initial_size = 1024, Allocator *allocator = nullptr,
- bool own_allocator = false,
- size_t buffer_minalign = AlignOf<largest_scalar_t>())
- : buf_(initial_size, allocator, own_allocator, buffer_minalign),
- num_field_loc(0),
- max_voffset_(0),
- nested(false),
- finished(false),
- minalign_(1),
- force_defaults_(false),
- dedup_vtables_(true),
- string_pool(nullptr) {
- EndianCheck();
- }
-
- // clang-format off
- /// @brief Move constructor for FlatBufferBuilder.
- #if !defined(FLATBUFFERS_CPP98_STL)
- FlatBufferBuilder(FlatBufferBuilder &&other)
- #else
- FlatBufferBuilder(FlatBufferBuilder &other)
- #endif // #if !defined(FLATBUFFERS_CPP98_STL)
- : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
- num_field_loc(0),
- max_voffset_(0),
- nested(false),
- finished(false),
- minalign_(1),
- force_defaults_(false),
- dedup_vtables_(true),
- string_pool(nullptr) {
- EndianCheck();
- // Default construct and swap idiom.
- // Lack of delegating constructors in vs2010 makes it more verbose than needed.
- Swap(other);
- }
- // clang-format on
-
- // clang-format off
- #if !defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
- /// @brief Move assignment operator for FlatBufferBuilder.
- FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
- // Move construct a temporary and swap idiom
- FlatBufferBuilder temp(std::move(other));
- Swap(temp);
- return *this;
- }
- // clang-format off
- #endif // defined(FLATBUFFERS_CPP98_STL)
- // clang-format on
-
- void Swap(FlatBufferBuilder &other) {
- using std::swap;
- buf_.swap(other.buf_);
- swap(num_field_loc, other.num_field_loc);
- swap(max_voffset_, other.max_voffset_);
- swap(nested, other.nested);
- swap(finished, other.finished);
- swap(minalign_, other.minalign_);
- swap(force_defaults_, other.force_defaults_);
- swap(dedup_vtables_, other.dedup_vtables_);
- swap(string_pool, other.string_pool);
- }
-
- ~FlatBufferBuilder() {
- if (string_pool) delete string_pool;
- }
-
- void Reset() {
- Clear(); // clear builder state
- buf_.reset(); // deallocate buffer
- }
-
- /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
- /// to construct another buffer.
- void Clear() {
- ClearOffsets();
- buf_.clear();
- nested = false;
- finished = false;
- minalign_ = 1;
- if (string_pool) string_pool->clear();
- }
-
- /// @brief The current size of the serialized buffer, counting from the end.
- /// @return Returns an `uoffset_t` with the current size of the buffer.
- uoffset_t GetSize() const { return buf_.size(); }
-
- /// @brief Get the serialized buffer (after you call `Finish()`).
- /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
- /// buffer.
- uint8_t *GetBufferPointer() const {
- Finished();
- return buf_.data();
- }
-
- /// @brief Get the serialized buffer (after you call `Finish()`) as a span.
- /// @return Returns a constructed flatbuffers::span that is a view over the
- /// FlatBuffer data inside the buffer.
- flatbuffers::span<uint8_t> GetBufferSpan() const {
- Finished();
- return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
- }
-
- /// @brief Get a pointer to an unfinished buffer.
- /// @return Returns a `uint8_t` pointer to the unfinished buffer.
- uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
-
- /// @brief Get the released pointer to the serialized buffer.
- /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
- /// @return A `FlatBuffer` that owns the buffer and its allocator and
- /// behaves similar to a `unique_ptr` with a deleter.
- FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
- DetachedBuffer ReleaseBufferPointer() {
- Finished();
- return buf_.release();
- }
-
- /// @brief Get the released DetachedBuffer.
- /// @return A `DetachedBuffer` that owns the buffer and its allocator.
- DetachedBuffer Release() {
- Finished();
- return buf_.release();
- }
-
- /// @brief Get the released pointer to the serialized buffer.
- /// @param size The size of the memory block containing
- /// the serialized `FlatBuffer`.
- /// @param offset The offset from the released pointer where the finished
- /// `FlatBuffer` starts.
- /// @return A raw pointer to the start of the memory block containing
- /// the serialized `FlatBuffer`.
- /// @remark If the allocator is owned, it gets deleted when the destructor is
- /// called..
- uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
- Finished();
- return buf_.release_raw(size, offset);
- }
-
- /// @brief get the minimum alignment this buffer needs to be accessed
- /// properly. This is only known once all elements have been written (after
- /// you call Finish()). You can use this information if you need to embed
- /// a FlatBuffer in some other buffer, such that you can later read it
- /// without first having to copy it into its own buffer.
- size_t GetBufferMinAlignment() const {
- Finished();
- return minalign_;
- }
-
- /// @cond FLATBUFFERS_INTERNAL
- 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
- // FlatBufferBuilder::Finish with your root table.
- // If you really need to access an unfinished buffer, call
- // GetCurrentBufferPointer instead.
- FLATBUFFERS_ASSERT(finished);
- }
- /// @endcond
-
- /// @brief In order to save space, fields that are set to their default value
- /// don't get serialized into the buffer.
- /// @param[in] fd When set to `true`, always serializes default values that
- /// are set. Optional fields which are not set explicitly, will still not be
- /// serialized.
- void ForceDefaults(bool fd) { force_defaults_ = fd; }
-
- /// @brief By default vtables are deduped in order to save space.
- /// @param[in] dedup When set to `true`, dedup vtables.
- void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
-
- /// @cond FLATBUFFERS_INTERNAL
- void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
-
- void TrackMinAlign(size_t elem_size) {
- if (elem_size > minalign_) minalign_ = elem_size;
- }
-
- void Align(size_t elem_size) {
- TrackMinAlign(elem_size);
- buf_.fill(PaddingBytes(buf_.size(), elem_size));
- }
-
- void PushFlatBuffer(const uint8_t *bytes, size_t size) {
- PushBytes(bytes, size);
- finished = true;
- }
-
- void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
-
- void PopBytes(size_t amount) { buf_.pop(amount); }
-
- template<typename T> void AssertScalarT() {
- // The code assumes power of 2 sizes and endian-swap-ability.
- static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
- }
-
- // Write a single aligned scalar to the buffer
- template<typename T> uoffset_t PushElement(T element) {
- AssertScalarT<T>();
- T litle_endian_element = EndianScalar(element);
- Align(sizeof(T));
- buf_.push_small(litle_endian_element);
- return GetSize();
- }
-
- template<typename T> uoffset_t PushElement(Offset<T> off) {
- // Special case for offsets: see ReferTo below.
- return PushElement(ReferTo(off.o));
- }
-
- // When writing fields, we track where they are, so we can create correct
- // vtables later.
- void TrackField(voffset_t field, uoffset_t off) {
- FieldLoc fl = { off, field };
- buf_.scratch_push_small(fl);
- num_field_loc++;
- max_voffset_ = (std::max)(max_voffset_, field);
- }
-
- // Like PushElement, but additionally tracks the field this represents.
- template<typename T> void AddElement(voffset_t field, T e, T def) {
- // We don't serialize values equal to the default.
- if (IsTheSameAs(e, def) && !force_defaults_) return;
- auto off = PushElement(e);
- TrackField(field, off);
- }
-
- template<typename T> void AddElement(voffset_t field, T e) {
- auto off = PushElement(e);
- TrackField(field, off);
- }
-
- template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
- if (off.IsNull()) return; // Don't store.
- AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
- }
-
- template<typename T> void AddStruct(voffset_t field, const T *structptr) {
- if (!structptr) return; // Default, don't store.
- Align(AlignOf<T>());
- buf_.push_small(*structptr);
- TrackField(field, GetSize());
- }
-
- void AddStructOffset(voffset_t field, uoffset_t off) {
- TrackField(field, off);
- }
-
- // Offsets initially are relative to the end of the buffer (downwards).
- // This function converts them to be relative to the current location
- // in the buffer (when stored here), pointing upwards.
- uoffset_t ReferTo(uoffset_t off) {
- // Align to ensure GetSize() below is correct.
- Align(sizeof(uoffset_t));
- // Offset must refer to something already in buffer.
- FLATBUFFERS_ASSERT(off && off <= GetSize());
- return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
- }
-
- void NotNested() {
- // If you hit this, you're trying to construct a Table/Vector/String
- // during the construction of its parent table (between the MyTableBuilder
- // and table.Finish().
- // Move the creation of these sub-objects to above the MyTableBuilder to
- // not get this assert.
- // Ignoring this assert may appear to work in simple cases, but the reason
- // it is here is that storing objects in-line may cause vtable offsets
- // to not fit anymore. It also leads to vtable duplication.
- FLATBUFFERS_ASSERT(!nested);
- // If you hit this, fields were added outside the scope of a table.
- FLATBUFFERS_ASSERT(!num_field_loc);
- }
-
- // From generated code (or from the parser), we call StartTable/EndTable
- // with a sequence of AddElement calls in between.
- uoffset_t StartTable() {
- NotNested();
- nested = true;
- return GetSize();
- }
-
- // This finishes one serialized object by generating the vtable if it's a
- // table, comparing it against existing vtables, and writing the
- // resulting vtable offset.
- uoffset_t EndTable(uoffset_t start) {
- // If you get this assert, a corresponding StartTable wasn't called.
- FLATBUFFERS_ASSERT(nested);
- // Write the vtable offset, which is the start of any Table.
- // We fill it's value later.
- auto vtableoffsetloc = PushElement<soffset_t>(0);
- // Write a vtable, which consists entirely of voffset_t elements.
- // It starts with the number of offsets, followed by a type id, followed
- // by the offsets themselves. In reverse:
- // Include space for the last offset and ensure empty tables have a
- // minimum size.
- max_voffset_ =
- (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
- FieldIndexToOffset(0));
- buf_.fill_big(max_voffset_);
- auto table_object_size = vtableoffsetloc - start;
- // Vtable use 16bit offsets.
- FLATBUFFERS_ASSERT(table_object_size < 0x10000);
- WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
- static_cast<voffset_t>(table_object_size));
- WriteScalar<voffset_t>(buf_.data(), max_voffset_);
- // Write the offsets into the table
- for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
- it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
- auto field_location = reinterpret_cast<FieldLoc *>(it);
- auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
- // If this asserts, it means you've set a field twice.
- FLATBUFFERS_ASSERT(
- !ReadScalar<voffset_t>(buf_.data() + field_location->id));
- WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
- }
- ClearOffsets();
- auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
- auto vt1_size = ReadScalar<voffset_t>(vt1);
- auto vt_use = GetSize();
- // See if we already have generated a vtable with this exact same
- // layout before. If so, make it point to the old one, remove this one.
- if (dedup_vtables_) {
- for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
- it += sizeof(uoffset_t)) {
- auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
- auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
- auto vt2_size = ReadScalar<voffset_t>(vt2);
- if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
- vt_use = *vt_offset_ptr;
- buf_.pop(GetSize() - vtableoffsetloc);
- break;
- }
- }
- // If this is a new vtable, remember it.
- if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
- // Fill the vtable offset we created above.
- // The offset points from the beginning of the object to where the
- // vtable is stored.
- // Offsets default direction is downward in memory for future format
- // flexibility (storing all vtables at the start of the file).
- WriteScalar(buf_.data_at(vtableoffsetloc),
- static_cast<soffset_t>(vt_use) -
- static_cast<soffset_t>(vtableoffsetloc));
-
- nested = false;
- return vtableoffsetloc;
- }
-
- FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
- uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
- return EndTable(start);
- }
-
- // This checks a required field has been set in a given table that has
- // just been constructed.
- template<typename T> void Required(Offset<T> table, voffset_t field);
-
- uoffset_t StartStruct(size_t alignment) {
- Align(alignment);
- return GetSize();
- }
-
- uoffset_t EndStruct() { return GetSize(); }
-
- void ClearOffsets() {
- buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
- num_field_loc = 0;
- max_voffset_ = 0;
- }
-
- // Aligns such that when "len" bytes are written, an object can be written
- // after it with "alignment" without padding.
- void PreAlign(size_t len, size_t alignment) {
- TrackMinAlign(alignment);
- buf_.fill(PaddingBytes(GetSize() + len, alignment));
- }
- template<typename T> void PreAlign(size_t len) {
- AssertScalarT<T>();
- PreAlign(len, sizeof(T));
- }
- /// @endcond
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// @param[in] str A const char pointer to the data to be stored as a string.
- /// @param[in] len The number of bytes that should be stored from `str`.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateString(const char *str, size_t len) {
- NotNested();
- PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
- buf_.fill(1);
- PushBytes(reinterpret_cast<const uint8_t *>(str), len);
- PushElement(static_cast<uoffset_t>(len));
- return Offset<String>(GetSize());
- }
-
- /// @brief Store a string in the buffer, which is null-terminated.
- /// @param[in] str A const char pointer to a C-string to add to the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateString(const char *str) {
- return CreateString(str, strlen(str));
- }
-
- /// @brief Store a string in the buffer, which is null-terminated.
- /// @param[in] str A char pointer to a C-string to add to the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateString(char *str) {
- return CreateString(str, strlen(str));
- }
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// @param[in] str A const reference to a std::string to store in the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateString(const std::string &str) {
- return CreateString(str.c_str(), str.length());
- }
-
- // clang-format off
- #ifdef FLATBUFFERS_HAS_STRING_VIEW
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// @param[in] str A const string_view to copy in to the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateString(flatbuffers::string_view str) {
- return CreateString(str.data(), str.size());
- }
- #endif // FLATBUFFERS_HAS_STRING_VIEW
- // clang-format on
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// @param[in] str A const pointer to a `String` struct to add to the buffer.
- /// @return Returns the offset in the buffer where the string starts
- Offset<String> CreateString(const String *str) {
- return str ? CreateString(str->c_str(), str->size()) : 0;
- }
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// @param[in] str A const reference to a std::string like type with support
- /// of T::c_str() and T::length() to store in the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- template<typename T> Offset<String> CreateString(const T &str) {
- return CreateString(str.data(), str.length());
- }
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// If a string with this exact contents has already been serialized before,
- /// instead simply returns the offset of the existing string.
- /// @param[in] str A const char pointer to the data to be stored as a string.
- /// @param[in] len The number of bytes that should be stored from `str`.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateSharedString(const char *str, size_t len) {
- if (!string_pool)
- string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
- auto size_before_string = buf_.size();
- // Must first serialize the string, since the set is all offsets into
- // buffer.
- auto off = CreateString(str, len);
- auto it = string_pool->find(off);
- // If it exists we reuse existing serialized data!
- if (it != string_pool->end()) {
- // We can remove the string we serialized.
- buf_.pop(buf_.size() - size_before_string);
- return *it;
- }
- // Record this string for future use.
- string_pool->insert(off);
- return off;
- }
-
-#ifdef FLATBUFFERS_HAS_STRING_VIEW
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// If a string with this exact contents has already been serialized before,
- /// instead simply returns the offset of the existing string.
- /// @param[in] str A const std::string_view to store in the buffer.
- /// @return Returns the offset in the buffer where the string starts
- Offset<String> CreateSharedString(const flatbuffers::string_view str) {
- return CreateSharedString(str.data(), str.size());
- }
-#else
- /// @brief Store a string in the buffer, which null-terminated.
- /// If a string with this exact contents has already been serialized before,
- /// instead simply returns the offset of the existing string.
- /// @param[in] str A const char pointer to a C-string to add to the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateSharedString(const char *str) {
- return CreateSharedString(str, strlen(str));
- }
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// If a string with this exact contents has already been serialized before,
- /// instead simply returns the offset of the existing string.
- /// @param[in] str A const reference to a std::string to store in the buffer.
- /// @return Returns the offset in the buffer where the string starts.
- Offset<String> CreateSharedString(const std::string &str) {
- return CreateSharedString(str.c_str(), str.length());
- }
-#endif
-
- /// @brief Store a string in the buffer, which can contain any binary data.
- /// If a string with this exact contents has already been serialized before,
- /// instead simply returns the offset of the existing string.
- /// @param[in] str A const pointer to a `String` struct to add to the buffer.
- /// @return Returns the offset in the buffer where the string starts
- Offset<String> CreateSharedString(const String *str) {
- return CreateSharedString(str->c_str(), str->size());
- }
-
- /// @cond FLATBUFFERS_INTERNAL
- uoffset_t EndVector(size_t len) {
- FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector.
- nested = false;
- return PushElement(static_cast<uoffset_t>(len));
- }
-
- void StartVector(size_t len, size_t elemsize) {
- NotNested();
- nested = true;
- PreAlign<uoffset_t>(len * elemsize);
- PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
- }
-
- // Call this right before StartVector/CreateVector if you want to force the
- // alignment to be something different than what the element size would
- // normally dictate.
- // This is useful when storing a nested_flatbuffer in a vector of bytes,
- // or when storing SIMD floats, etc.
- void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
- FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
- PreAlign(len * elemsize, alignment);
- }
-
- // Similar to ForceVectorAlignment but for String fields.
- void ForceStringAlignment(size_t len, size_t alignment) {
- FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
- PreAlign((len + 1) * sizeof(char), alignment);
- }
-
- /// @endcond
-
- /// @brief Serialize an array into a FlatBuffer `vector`.
- /// @tparam T The data type of the array elements.
- /// @param[in] v A pointer to the array of type `T` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
- // If this assert hits, you're specifying a template argument that is
- // causing the wrong overload to be selected, remove it.
- AssertScalarT<T>();
- StartVector(len, sizeof(T));
- if (len == 0) { return Offset<Vector<T>>(EndVector(len)); }
- // clang-format off
- #if FLATBUFFERS_LITTLEENDIAN
- PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
- #else
- if (sizeof(T) == 1) {
- PushBytes(reinterpret_cast<const uint8_t *>(v), len);
- } else {
- for (auto i = len; i > 0; ) {
- PushElement(v[--i]);
- }
- }
- #endif
- // clang-format on
- return Offset<Vector<T>>(EndVector(len));
- }
-
- template<typename T>
- Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
- StartVector(len, sizeof(Offset<T>));
- for (auto i = len; i > 0;) { PushElement(v[--i]); }
- return Offset<Vector<Offset<T>>>(EndVector(len));
- }
-
- /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
- /// @tparam T The data type of the `std::vector` elements.
- /// @param v A const reference to the `std::vector` to serialize into the
- /// buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
- return CreateVector(data(v), v.size());
- }
-
- // vector<bool> may be implemented using a bit-set, so we can't access it as
- // an array. Instead, read elements manually.
- // Background: https://isocpp.org/blog/2012/11/on-vectorbool
- Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
- StartVector(v.size(), sizeof(uint8_t));
- for (auto i = v.size(); i > 0;) {
- PushElement(static_cast<uint8_t>(v[--i]));
- }
- return Offset<Vector<uint8_t>>(EndVector(v.size()));
- }
-
- // clang-format off
- #ifndef FLATBUFFERS_CPP98_STL
- /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
- /// This is a convenience function that takes care of iteration for you.
- /// @tparam T The data type of the `std::vector` elements.
- /// @param f A function that takes the current iteration 0..vector_size-1 and
- /// returns any type that you can construct a FlatBuffers vector out of.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
- const std::function<T (size_t i)> &f) {
- std::vector<T> elems(vector_size);
- for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
- return CreateVector(elems);
- }
- #endif
- // clang-format on
-
- /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
- /// This is a convenience function that takes care of iteration for you.
- /// @tparam T The data type of the `std::vector` elements.
- /// @param f A function that takes the current iteration 0..vector_size-1,
- /// and the state parameter returning any type that you can construct a
- /// FlatBuffers vector out of.
- /// @param state State passed to f.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename F, typename S>
- Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
- std::vector<T> elems(vector_size);
- for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
- return CreateVector(elems);
- }
-
- /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
- /// This is a convenience function for a common case.
- /// @param v A const reference to the `std::vector` to serialize into the
- /// buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- Offset<Vector<Offset<String>>> CreateVectorOfStrings(
- const std::vector<std::string> &v) {
- std::vector<Offset<String>> offsets(v.size());
- for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
- return CreateVector(offsets);
- }
-
- /// @brief Serialize an array of structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the struct array elements.
- /// @param[in] v A pointer to the array of type `T` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T>
- Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
- StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
- PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
- return Offset<Vector<const T *>>(EndVector(len));
- }
-
- /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the struct array elements.
- /// @tparam S The data type of the native struct array elements.
- /// @param[in] v A pointer to the array of type `S` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @param[in] pack_func Pointer to a function to convert the native struct
- /// to the FlatBuffer struct.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfNativeStructs(
- const S *v, size_t len, T((*const pack_func)(const S &))) {
- FLATBUFFERS_ASSERT(pack_func);
- std::vector<T> vv(len);
- std::transform(v, v + len, vv.begin(), pack_func);
- return CreateVectorOfStructs<T>(data(vv), vv.size());
- }
-
- /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the struct array elements.
- /// @tparam S The data type of the native struct array elements.
- /// @param[in] v A pointer to the array of type `S` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
- size_t len) {
- extern T Pack(const S &);
- return CreateVectorOfNativeStructs(v, len, Pack);
- }
-
- // clang-format off
- #ifndef FLATBUFFERS_CPP98_STL
- /// @brief Serialize an array of structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the struct array elements.
- /// @param[in] filler A function that takes the current iteration 0..vector_size-1
- /// and a pointer to the struct that must be filled.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- /// This is mostly useful when flatbuffers are generated with mutation
- /// accessors.
- template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
- size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
- T* structs = StartVectorOfStructs<T>(vector_size);
- for (size_t i = 0; i < vector_size; i++) {
- filler(i, structs);
- structs++;
- }
- return EndVectorOfStructs<T>(vector_size);
- }
- #endif
- // clang-format on
-
- /// @brief Serialize an array of structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the struct array elements.
- /// @param[in] f A function that takes the current iteration 0..vector_size-1,
- /// a pointer to the struct that must be filled and the state argument.
- /// @param[in] state Arbitrary state to pass to f.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- /// This is mostly useful when flatbuffers are generated with mutation
- /// accessors.
- template<typename T, typename F, typename S>
- Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
- S *state) {
- T *structs = StartVectorOfStructs<T>(vector_size);
- for (size_t i = 0; i < vector_size; i++) {
- f(i, structs, state);
- structs++;
- }
- return EndVectorOfStructs<T>(vector_size);
- }
-
- /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
- /// @tparam T The data type of the `std::vector` struct elements.
- /// @param[in] v A const reference to the `std::vector` of structs to
- /// serialize into the buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename Alloc>
- Offset<Vector<const T *>> CreateVectorOfStructs(
- const std::vector<T, Alloc> &v) {
- return CreateVectorOfStructs(data(v), v.size());
- }
-
- /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
- /// `vector`.
- /// @tparam T The data type of the `std::vector` struct elements.
- /// @tparam S The data type of the `std::vector` native struct elements.
- /// @param[in] v A const reference to the `std::vector` of structs to
- /// serialize into the buffer as a `vector`.
- /// @param[in] pack_func Pointer to a function to convert the native struct
- /// to the FlatBuffer struct.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfNativeStructs(
- const std::vector<S> &v, T((*const pack_func)(const S &))) {
- return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
- }
-
- /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
- /// `vector`.
- /// @tparam T The data type of the `std::vector` struct elements.
- /// @tparam S The data type of the `std::vector` native struct elements.
- /// @param[in] v A const reference to the `std::vector` of structs to
- /// serialize into the buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfNativeStructs(
- const std::vector<S> &v) {
- return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
- }
-
- /// @cond FLATBUFFERS_INTERNAL
- template<typename T> struct StructKeyComparator {
- bool operator()(const T &a, const T &b) const {
- return a.KeyCompareLessThan(&b);
- }
-
- FLATBUFFERS_DELETE_FUNC(
- StructKeyComparator &operator=(const StructKeyComparator &));
- };
- /// @endcond
-
- /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
- /// in sorted order.
- /// @tparam T The data type of the `std::vector` struct elements.
- /// @param[in] v A const reference to the `std::vector` of structs to
- /// serialize into the buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T>
- Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
- return CreateVectorOfSortedStructs(data(*v), v->size());
- }
-
- /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
- /// `vector` in sorted order.
- /// @tparam T The data type of the `std::vector` struct elements.
- /// @tparam S The data type of the `std::vector` native struct elements.
- /// @param[in] v A const reference to the `std::vector` of structs to
- /// serialize into the buffer as a `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
- std::vector<S> *v) {
- return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
- }
-
- /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
- /// order.
- /// @tparam T The data type of the struct array elements.
- /// @param[in] v A pointer to the array of type `T` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T>
- Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
- std::sort(v, v + len, StructKeyComparator<T>());
- return CreateVectorOfStructs(v, len);
- }
-
- /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
- /// sorted order.
- /// @tparam T The data type of the struct array elements.
- /// @tparam S The data type of the native struct array elements.
- /// @param[in] v A pointer to the array of type `S` to serialize into the
- /// buffer as a `vector`.
- /// @param[in] len The number of elements to serialize.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T, typename S>
- Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
- size_t len) {
- extern T Pack(const S &);
- typedef T (*Pack_t)(const S &);
- std::vector<T> vv(len);
- std::transform(v, v + len, vv.begin(), static_cast<Pack_t &>(Pack));
- return CreateVectorOfSortedStructs<T>(vv, len);
- }
-
- /// @cond FLATBUFFERS_INTERNAL
- template<typename T> struct TableKeyComparator {
- TableKeyComparator(vector_downward &buf) : buf_(buf) {}
- TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
- bool operator()(const Offset<T> &a, const Offset<T> &b) const {
- auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
- auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
- return table_a->KeyCompareLessThan(table_b);
- }
- vector_downward &buf_;
-
- private:
- FLATBUFFERS_DELETE_FUNC(
- TableKeyComparator &operator=(const TableKeyComparator &other));
- };
- /// @endcond
-
- /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
- /// in sorted order.
- /// @tparam T The data type that the offset refers to.
- /// @param[in] v An array of type `Offset<T>` that contains the `table`
- /// offsets to store in the buffer in sorted order.
- /// @param[in] len The number of elements to store in the `vector`.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T>
- Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
- size_t len) {
- std::sort(v, v + len, TableKeyComparator<T>(buf_));
- return CreateVector(v, len);
- }
-
- /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
- /// in sorted order.
- /// @tparam T The data type that the offset refers to.
- /// @param[in] v An array of type `Offset<T>` that contains the `table`
- /// offsets to store in the buffer in sorted order.
- /// @return Returns a typed `Offset` into the serialized data indicating
- /// where the vector is stored.
- template<typename T>
- Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
- std::vector<Offset<T>> *v) {
- return CreateVectorOfSortedTables(data(*v), v->size());
- }
-
- /// @brief Specialized version of `CreateVector` for non-copying use cases.
- /// Write the data any time later to the returned buffer pointer `buf`.
- /// @param[in] len The number of elements to store in the `vector`.
- /// @param[in] elemsize The size of each element in the `vector`.
- /// @param[out] buf A pointer to a `uint8_t` pointer that can be
- /// written to at a later time to serialize the data into a `vector`
- /// in the buffer.
- uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
- uint8_t **buf) {
- NotNested();
- StartVector(len, elemsize);
- buf_.make_space(len * elemsize);
- auto vec_start = GetSize();
- auto vec_end = EndVector(len);
- *buf = buf_.data_at(vec_start);
- return vec_end;
- }
-
- /// @brief Specialized version of `CreateVector` for non-copying use cases.
- /// Write the data any time later to the returned buffer pointer `buf`.
- /// @tparam T The data type of the data that will be stored in the buffer
- /// as a `vector`.
- /// @param[in] len The number of elements to store in the `vector`.
- /// @param[out] buf A pointer to a pointer of type `T` that can be
- /// written to at a later time to serialize the data into a `vector`
- /// in the buffer.
- template<typename T>
- Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
- AssertScalarT<T>();
- return CreateUninitializedVector(len, sizeof(T),
- reinterpret_cast<uint8_t **>(buf));
- }
-
- template<typename T>
- Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
- T **buf) {
- return CreateUninitializedVector(len, sizeof(T),
- reinterpret_cast<uint8_t **>(buf));
- }
-
- // @brief Create a vector of scalar type T given as input a vector of scalar
- // type U, useful with e.g. pre "enum class" enums, or any existing scalar
- // data of the wrong type.
- template<typename T, typename U>
- Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
- AssertScalarT<T>();
- AssertScalarT<U>();
- StartVector(len, sizeof(T));
- for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
- return Offset<Vector<T>>(EndVector(len));
- }
-
- /// @brief Write a struct by itself, typically to be part of a union.
- template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
- NotNested();
- Align(AlignOf<T>());
- buf_.push_small(structobj);
- return Offset<const T *>(GetSize());
- }
-
- /// @brief The length of a FlatBuffer file header.
- static const size_t kFileIdentifierLength = 4;
-
- /// @brief Finish serializing a buffer by writing the root offset.
- /// @param[in] file_identifier If a `file_identifier` is given, the buffer
- /// will be prefixed with a standard FlatBuffers file header.
- template<typename T>
- void Finish(Offset<T> root, const char *file_identifier = nullptr) {
- Finish(root.o, file_identifier, false);
- }
-
- /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
- /// buffer following the size field). These buffers are NOT compatible
- /// with standard buffers created by Finish, i.e. you can't call GetRoot
- /// on them, you have to use GetSizePrefixedRoot instead.
- /// All >32 bit quantities in this buffer will be aligned when the whole
- /// size pre-fixed buffer is aligned.
- /// These kinds of buffers are useful for creating a stream of FlatBuffers.
- template<typename T>
- void FinishSizePrefixed(Offset<T> root,
- const char *file_identifier = nullptr) {
- Finish(root.o, file_identifier, true);
- }
-
- void SwapBufAllocator(FlatBufferBuilder &other) {
- buf_.swap_allocator(other.buf_);
- }
-
- protected:
- // You shouldn't really be copying instances of this class.
- FlatBufferBuilder(const FlatBufferBuilder &);
- FlatBufferBuilder &operator=(const FlatBufferBuilder &);
-
- void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
- NotNested();
- buf_.clear_scratch();
- // This will cause the whole buffer to be aligned.
- PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
- (file_identifier ? kFileIdentifierLength : 0),
- minalign_);
- if (file_identifier) {
- FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
- PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
- kFileIdentifierLength);
- }
- PushElement(ReferTo(root)); // Location of root.
- if (size_prefix) { PushElement(GetSize()); }
- finished = true;
- }
-
- struct FieldLoc {
- uoffset_t off;
- voffset_t id;
- };
-
- vector_downward buf_;
-
- // Accumulating offsets of table members while it is being built.
- // We store these in the scratch pad of buf_, after the vtable offsets.
- uoffset_t num_field_loc;
- // Track how much of the vtable is in use, so we can output the most compact
- // possible vtable.
- voffset_t max_voffset_;
-
- // Ensure objects are not nested.
- bool nested;
-
- // Ensure the buffer is finished before it is being accessed.
- bool finished;
-
- size_t minalign_;
-
- bool force_defaults_; // Serialize values equal to their defaults anyway.
-
- bool dedup_vtables_;
-
- struct StringOffsetCompare {
- StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
- bool operator()(const Offset<String> &a, const Offset<String> &b) const {
- auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
- auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
- return StringLessThan(stra->data(), stra->size(), strb->data(),
- strb->size());
- }
- const vector_downward *buf_;
- };
-
- // For use with CreateSharedString. Instantiated on first use only.
- typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
- StringOffsetMap *string_pool;
-
- private:
- // Allocates space for a vector of structures.
- // Must be completed with EndVectorOfStructs().
- template<typename T> T *StartVectorOfStructs(size_t vector_size) {
- StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
- return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
- }
-
- // End the vector of structues in the flatbuffers.
- // Vector should have previously be started with StartVectorOfStructs().
- template<typename T>
- Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
- return Offset<Vector<const T *>>(EndVector(vector_size));
- }
-};
-/// @}
-
-/// @cond FLATBUFFERS_INTERNAL
-// Helpers to get a typed pointer to the root object contained in the buffer.
-template<typename T> T *GetMutableRoot(void *buf) {
- EndianCheck();
- return reinterpret_cast<T *>(
- reinterpret_cast<uint8_t *>(buf) +
- EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
-}
-
-template<typename T> const T *GetRoot(const void *buf) {
- return GetMutableRoot<T>(const_cast<void *>(buf));
-}
-
-template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
- return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
-}
-
-/// Helpers to get a typed pointer to objects that are currently being built.
-/// @warning Creating new objects will lead to reallocations and invalidates
-/// the pointer!
-template<typename T>
-T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
- return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
- offset.o);
-}
-
-template<typename T>
-const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
- return GetMutableTemporaryPointer<T>(fbb, offset);
-}
-
-/// @brief Get a pointer to the the file_identifier section of the buffer.
-/// @return Returns a const char pointer to the start of the file_identifier
-/// characters in the buffer. The returned char * has length
-/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
-/// This function is UNDEFINED for FlatBuffers whose schema does not include
-/// a file_identifier (likely points at padding or the start of a the root
-/// vtable).
-inline const char *GetBufferIdentifier(const void *buf,
- bool size_prefixed = false) {
- return reinterpret_cast<const char *>(buf) +
- ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
-}
-
-// Helper to see if the identifier in a buffer has the expected value.
-inline bool BufferHasIdentifier(const void *buf, const char *identifier,
- bool size_prefixed = false) {
- return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
- FlatBufferBuilder::kFileIdentifierLength) == 0;
-}
-
-// Helper class to verify the integrity of a FlatBuffer
-class Verifier FLATBUFFERS_FINAL_CLASS {
- public:
- Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
- uoffset_t _max_tables = 1000000, bool _check_alignment = true)
- : buf_(buf),
- size_(buf_len),
- depth_(0),
- max_depth_(_max_depth),
- num_tables_(0),
- max_tables_(_max_tables),
- upper_bound_(0),
- check_alignment_(_check_alignment) {
- FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
- }
-
- // Central location where any verification failures register.
- bool Check(bool ok) const {
- // clang-format off
- #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
- FLATBUFFERS_ASSERT(ok);
- #endif
- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
- if (!ok)
- upper_bound_ = 0;
- #endif
- // clang-format on
- return ok;
- }
-
- // Verify any range within the buffer.
- bool Verify(size_t elem, size_t elem_len) const {
- // clang-format off
- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
- auto upper_bound = elem + elem_len;
- if (upper_bound_ < upper_bound)
- upper_bound_ = upper_bound;
- #endif
- // clang-format on
- return Check(elem_len < size_ && elem <= size_ - elem_len);
- }
-
- template<typename T> bool VerifyAlignment(size_t elem) const {
- return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
- }
-
- // Verify a range indicated by sizeof(T).
- template<typename T> bool Verify(size_t elem) const {
- return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
- }
-
- bool VerifyFromPointer(const uint8_t *p, size_t len) {
- auto o = static_cast<size_t>(p - buf_);
- return Verify(o, len);
- }
-
- // Verify relative to a known-good base pointer.
- bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
- return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
- }
-
- template<typename T>
- bool Verify(const uint8_t *base, voffset_t elem_off) const {
- return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
- }
-
- // Verify a pointer (may be NULL) of a table type.
- template<typename T> bool VerifyTable(const T *table) {
- return !table || table->Verify(*this);
- }
-
- // Verify a pointer (may be NULL) of any vector type.
- template<typename T> bool VerifyVector(const Vector<T> *vec) const {
- return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
- sizeof(T));
- }
-
- // Verify a pointer (may be NULL) of a vector to struct.
- template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
- return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
- }
-
- // Verify a pointer (may be NULL) to string.
- bool VerifyString(const String *str) const {
- size_t end;
- return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
- 1, &end) &&
- Verify(end, 1) && // Must have terminator
- Check(buf_[end] == '\0')); // Terminating byte must be 0.
- }
-
- // Common code between vectors and strings.
- bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
- size_t *end = nullptr) const {
- auto veco = static_cast<size_t>(vec - buf_);
- // Check we can read the size field.
- if (!Verify<uoffset_t>(veco)) 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;
- if (end) *end = veco + byte_size;
- return Verify(veco, byte_size);
- }
-
- // Special case for string contents, after the above has been called.
- bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
- if (vec) {
- for (uoffset_t i = 0; i < vec->size(); i++) {
- if (!VerifyString(vec->Get(i))) return false;
- }
- }
- return true;
- }
-
- // Special case for table contents, after the above has been called.
- template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
- if (vec) {
- for (uoffset_t i = 0; i < vec->size(); i++) {
- if (!vec->Get(i)->Verify(*this)) return false;
- }
- }
- return true;
- }
-
- __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
- const uint8_t *table) {
- // Check the vtable offset.
- auto tableo = static_cast<size_t>(table - buf_);
- if (!Verify<soffset_t>(tableo)) return false;
- // This offset may be signed, but doing the subtraction unsigned always
- // gives the result we want.
- auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
- // Check the vtable size field, then check vtable fits in its entirety.
- return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
- VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
- Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
- }
-
- template<typename T>
- bool VerifyBufferFromStart(const char *identifier, size_t start) {
- if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
- BufferHasIdentifier(buf_ + start, identifier)))) {
- return false;
- }
-
- // Call T::Verify, which must be in the generated code for this type.
- auto o = VerifyOffset(start);
- return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
- // clang-format off
- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
- && GetComputedSize()
- #endif
- ;
- // clang-format on
- }
-
- // Verify this whole buffer, starting with root type T.
- template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
-
- template<typename T> bool VerifyBuffer(const char *identifier) {
- return VerifyBufferFromStart<T>(identifier, 0);
- }
-
- template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
- return Verify<uoffset_t>(0U) &&
- ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
- VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
- }
-
- uoffset_t VerifyOffset(size_t start) const {
- if (!Verify<uoffset_t>(start)) return 0;
- auto o = ReadScalar<uoffset_t>(buf_ + start);
- // May not point to itself.
- if (!Check(o != 0)) return 0;
- // Can't wrap around / buffers are max 2GB.
- if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
- // Must be inside the buffer to create a pointer from it (pointer outside
- // buffer is UB).
- if (!Verify(start + o, 1)) return 0;
- return o;
- }
-
- uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
- return VerifyOffset(static_cast<size_t>(base - buf_) + start);
- }
-
- // 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;
- }
-
- // Returns the message size in bytes
- size_t GetComputedSize() const {
- // clang-format off
- #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
- uintptr_t size = upper_bound_;
- // Align the size to uoffset_t
- size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
- return (size > size_) ? 0 : size;
- #else
- // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
- (void)upper_bound_;
- FLATBUFFERS_ASSERT(false);
- return 0;
- #endif
- // clang-format on
- }
-
- private:
- const uint8_t *buf_;
- size_t size_;
- uoffset_t depth_;
- uoffset_t max_depth_;
- uoffset_t num_tables_;
- uoffset_t max_tables_;
- mutable size_t upper_bound_;
- bool check_alignment_;
-};
-
-// Convenient way to bundle a buffer and its length, to pass it around
-// typed by its root.
-// A BufferRef does not own its buffer.
-struct BufferRefBase {}; // for std::is_base_of
-template<typename T> struct BufferRef : BufferRefBase {
- BufferRef() : buf(nullptr), len(0), must_free(false) {}
- BufferRef(uint8_t *_buf, uoffset_t _len)
- : buf(_buf), len(_len), must_free(false) {}
-
- ~BufferRef() {
- if (must_free) free(buf);
- }
-
- const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
-
- bool Verify() {
- Verifier verifier(buf, len);
- return verifier.VerifyBuffer<T>(nullptr);
- }
-
- uint8_t *buf;
- uoffset_t len;
- bool must_free;
-};
-
-// "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.
-
-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 reinterpret_cast<T>(&data_[o]);
- }
-
- const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
- uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
-
- private:
- // private constructor & copy constructor: you obtain instances of this
- // class by pointing to existing data only
- Struct();
- Struct(const Struct &);
- Struct &operator=(const Struct &);
-
- uint8_t data_[1];
-};
-
-// "tables" use an offset table (possibly shared) that allows fields to be
-// omitted and added at will, but uses an extra indirection to read.
-class Table {
- public:
- const uint8_t *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> P GetPointer(voffset_t field) {
- auto field_offset = GetOptionalFieldOffset(field);
- auto p = data_ + field_offset;
- return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
- : nullptr;
- }
- template<typename P> P GetPointer(voffset_t field) const {
- return const_cast<Table *>(this)->GetPointer<P>(field);
- }
-
- template<typename P> P GetStruct(voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- auto p = const_cast<uint8_t *>(data_ + field_offset);
- return field_offset ? reinterpret_cast<P>(p) : nullptr;
- }
-
- template<typename Raw, typename Face>
- flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- auto p = data_ + field_offset;
- return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
- : Optional<Face>();
- }
-
- template<typename T> bool SetField(voffset_t field, T val, T def) {
- auto field_offset = GetOptionalFieldOffset(field);
- if (!field_offset) return IsTheSameAs(val, def);
- WriteScalar(data_ + field_offset, val);
- return true;
- }
- template<typename T> bool SetField(voffset_t field, T val) {
- auto field_offset = GetOptionalFieldOffset(field);
- if (!field_offset) return false;
- WriteScalar(data_ + field_offset, val);
- return true;
- }
-
- bool SetPointer(voffset_t field, const uint8_t *val) {
- auto field_offset = GetOptionalFieldOffset(field);
- if (!field_offset) return false;
- WriteScalar(data_ + field_offset,
- static_cast<uoffset_t>(val - (data_ + field_offset)));
- return true;
- }
-
- uint8_t *GetAddressOf(voffset_t field) {
- auto field_offset = GetOptionalFieldOffset(field);
- return field_offset ? data_ + field_offset : nullptr;
- }
- const uint8_t *GetAddressOf(voffset_t field) const {
- return const_cast<Table *>(this)->GetAddressOf(field);
- }
-
- 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 &verifier) const {
- return verifier.VerifyTableStart(data_);
- }
-
- // Verify a particular field.
- template<typename T>
- bool VerifyField(const Verifier &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.Verify<T>(data_, field_offset);
- }
-
- // VerifyField for required fields.
- template<typename T>
- bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- return verifier.Check(field_offset != 0) &&
- verifier.Verify<T>(data_, field_offset);
- }
-
- // Versions for offsets.
- bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- return !field_offset || verifier.VerifyOffset(data_, field_offset);
- }
-
- bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- return verifier.Check(field_offset != 0) &&
- verifier.VerifyOffset(data_, field_offset);
- }
-
- private:
- // private constructor & copy constructor: you obtain instances of this
- // class by pointing to existing data only
- Table();
- Table(const Table &other);
- Table &operator=(const Table &);
-
- uint8_t data_[1];
-};
-
-// This specialization allows avoiding warnings like:
-// MSVC C4800: type: forcing value to bool 'true' or 'false'.
-template<>
-inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
- voffset_t field) const {
- auto field_offset = GetOptionalFieldOffset(field);
- auto p = data_ + field_offset;
- return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
- : Optional<bool>();
-}
-
-template<typename T>
-void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
- auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
- bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
- // If this fails, the caller will show what field needs to be set.
- FLATBUFFERS_ASSERT(ok);
- (void)ok;
-}
/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
/// it is the opposite transformation of GetRoot().
@@ -2719,7 +58,7 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
// file_identifier, and alignment padding) to see which points to the root.
// None of the other values can "impersonate" the root since they will either
// be 0 or four ASCII characters.
- static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
+ static_assert(flatbuffers::kFileIdentifierLength == sizeof(uoffset_t),
"file_identifier is assumed to be the same size as uoffset_t");
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
possible_roots; possible_roots--) {
@@ -2737,8 +76,9 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
}
/// @brief This return the prefixed size of a FlatBuffer.
-inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
- return ReadScalar<uoffset_t>(buf);
+template<typename SizeT = uoffset_t>
+inline SizeT GetPrefixedSize(const uint8_t *buf) {
+ return ReadScalar<SizeT>(buf);
}
// Base class for native objects (FlatBuffer data de-serialized into native
@@ -2755,16 +95,9 @@ struct NativeTable {};
/// if you wish. The resolver does the opposite lookup, for when the object
/// is being serialized again.
typedef uint64_t hash_value_t;
-// clang-format off
-#ifdef FLATBUFFERS_CPP98_STL
- typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
- typedef hash_value_t (*rehasher_function_t)(void *pointer);
-#else
- typedef std::function<void (void **pointer_adr, hash_value_t hash)>
- resolver_function_t;
- typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
-#endif
-// clang-format on
+typedef std::function<void(void **pointer_adr, hash_value_t hash)>
+ resolver_function_t;
+typedef std::function<hash_value_t(void *pointer)> rehasher_function_t;
// Helper function to test if a field is present, using any of the field
// enums in the generated code.
@@ -2821,7 +154,7 @@ inline int LookupEnum(const char **names, const char *name) {
// Minimal reflection via code generation.
// Besides full-fat reflection (see reflection.h) and parsing/printing by
-// loading schemas (see idl.h), we can also have code generation for mimimal
+// loading schemas (see idl.h), we can also have code generation for minimal
// reflection data which allows pretty-printing and other uses without needing
// a schema or a parser.
// Generate code with --reflect-types (types only) or --reflect-names (names
@@ -2896,27 +229,13 @@ struct TypeTable {
};
// String which identifies the current version of FlatBuffers.
-// flatbuffer_version_string is used by Google developers to identify which
-// applications uploaded to Google Play are using this library. This allows
-// the development team at Google to determine the popularity of the library.
-// How it works: Applications that are uploaded to the Google Play Store are
-// scanned for this version string. We track which applications are using it
-// to measure popularity. You are free to remove it (of course) but we would
-// appreciate if you left it in.
+inline const char *flatbuffers_version_string() {
+ return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
+}
-// Weak linkage is culled by VS & doesn't work on cygwin.
// clang-format off
-#if !defined(_WIN32) && !defined(__CYGWIN__)
-
-extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
-volatile __attribute__((weak)) const char *flatbuffer_version_string =
- "FlatBuffers "
- FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
- FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
- FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
-
-#endif // !defined(_WIN32) && !defined(__CYGWIN__)
-
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
inline E operator | (E lhs, E rhs){\
return E(T(lhs) | T(rhs));\
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h
index a770983dca..77421b82c0 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h
@@ -612,7 +612,27 @@ class Table {
}
// Verify a particular field.
- template<typename T> bool VerifyField(const Verifier<Iter> &verifier,
+ template<typename T>
+ bool VerifyField(const Verifier<Iter> &verifier, voffset_t field,
+ size_t align) const {
+ // Calling GetOptionalFieldOffset should be safe now thanks to
+ // VerifyTable().
+ auto field_offset = GetOptionalFieldOffset(field);
+ // Check the actual field.
+ return !field_offset || verifier.template VerifyField<T>(data_, field_offset, align);
+ }
+
+ // VerifyField for required fields.
+ template<typename T>
+ bool VerifyFieldRequired(const Verifier<Iter> &verifier, voffset_t field,
+ size_t align) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) &&
+ verifier.template VerifyField<T>(data_, field_offset, align);
+ }
+
+ // Versions for offsets.
+ template<typename T> bool VerifyOffset(const Verifier<Iter> &verifier,
voffset_t field) const {
// Calling GetOptionalFieldOffset should be safe now thanks to
// VerifyTable().
@@ -621,13 +641,12 @@ class Table {
return !field_offset || verifier.template Verify<T>(data_ + field_offset);
}
- // VerifyField for required fields.
- template<typename T> bool VerifyFieldRequired(const Verifier<Iter> &verifier,
+ template<typename T> bool VerifyOffsetRequired(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_;
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatc.h b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h
index 1466b3651d..71ea11bd71 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/flatc.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h
@@ -19,8 +19,11 @@
#include <functional>
#include <limits>
+#include <list>
+#include <memory>
#include <string>
+#include "code_generator.h"
#include "flatbuffers.h"
#include "idl.h"
#include "util.h"
@@ -30,29 +33,43 @@ namespace flatbuffers {
extern void LogCompilerWarn(const std::string &warn);
extern void LogCompilerError(const std::string &err);
+struct FlatCOptions {
+ IDLOptions opts;
+
+ std::string program_name;
+
+ std::string output_path;
+
+ 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;
+ size_t binary_files_from = std::numeric_limits<size_t>::max();
+ std::string conform_to_schema;
+ std::string annotate_schema;
+ bool annotate_include_vector_contents = true;
+ bool any_generator = false;
+ bool print_make_rules = false;
+ bool raw_binary = false;
+ bool schema_binary = false;
+ bool grpc_enabled = false;
+ bool requires_bfbs = false;
+ bool file_names_only = false;
+
+ std::vector<std::shared_ptr<CodeGenerator>> generators;
+};
+
+struct FlatCOption {
+ std::string short_opt;
+ std::string long_opt;
+ std::string parameter;
+ std::string description;
+};
+
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);
@@ -61,28 +78,29 @@ class FlatCompiler {
// 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;
+ InitParams() : warn_fn(nullptr), error_fn(nullptr) {}
+
WarnFn warn_fn;
ErrorFn error_fn;
};
explicit FlatCompiler(const InitParams &params) : params_(params) {}
- int Compile(int argc, const char **argv);
+ bool RegisterCodeGenerator(const FlatCOption &option,
+ std::shared_ptr<CodeGenerator> code_generator);
+
+ int Compile(const FlatCOptions &options);
- std::string GetUsageString(const char *program_name) const;
+ std::string GetShortUsageString(const std::string &program_name) const;
+ std::string GetUsageString(const std::string &program_name) const;
+
+ // Parse the FlatC options from command line arguments.
+ FlatCOptions ParseFromCommandLineArguments(int argc, const char **argv);
private:
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
const std::string &contents,
- std::vector<const char *> &include_directories) const;
+ const std::vector<const char *> &include_directories) const;
void LoadBinarySchema(Parser &parser, const std::string &filename,
const std::string &contents);
@@ -92,6 +110,19 @@ class FlatCompiler {
void Error(const std::string &err, bool usage = true,
bool show_exe_name = true) const;
+ void AnnotateBinaries(const uint8_t *binary_schema,
+ uint64_t binary_schema_size,
+ const FlatCOptions &options);
+
+ void ValidateOptions(const FlatCOptions &options);
+
+ Parser GetConformParser(const FlatCOptions &options);
+
+ std::unique_ptr<Parser> GenerateCode(const FlatCOptions &options,
+ Parser &conform_parser);
+
+ std::map<std::string, std::shared_ptr<CodeGenerator>> code_generators_;
+
InitParams params_;
};
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h
index d855b67731..1fdffb424e 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h
@@ -17,6 +17,7 @@
#ifndef FLATBUFFERS_FLEXBUFFERS_H_
#define FLATBUFFERS_FLEXBUFFERS_H_
+#include <algorithm>
#include <map>
// Used to select STL variant.
#include "base.h"
@@ -53,7 +54,7 @@ enum Type {
FBT_INT = 1,
FBT_UINT = 2,
FBT_FLOAT = 3,
- // Types above stored inline, types below store an offset.
+ // Types above stored inline, types below (except FBT_BOOL) store an offset.
FBT_KEY = 4,
FBT_STRING = 5,
FBT_INDIRECT_INT = 6,
@@ -81,6 +82,8 @@ enum Type {
FBT_BOOL = 26,
FBT_VECTOR_BOOL =
36, // To Allow the same type of conversion of type to vector type
+
+ FBT_MAX_TYPE = 37
};
inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }
@@ -154,8 +157,10 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
// 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)
+ #if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
+ // This is 64-bit Windows only, __movsb does not work on 32-bit Windows.
uint64_t u = 0;
__movsb(reinterpret_cast<uint8_t *>(&u),
reinterpret_cast<const uint8_t *>(data), byte_width);
@@ -319,8 +324,8 @@ class FixedTypedVector : public Object {
return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
}
- Type ElementType() { return type_; }
- uint8_t size() { return len_; }
+ Type ElementType() const { return type_; }
+ uint8_t size() const { return len_; }
private:
Type type_;
@@ -368,10 +373,7 @@ void AppendToString(std::string &s, T &&v, bool keys_quoted) {
class Reference {
public:
Reference()
- : data_(nullptr),
- parent_width_(0),
- byte_width_(BIT_WIDTH_8),
- type_(FBT_NULL) {}
+ : data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
Type type)
@@ -381,10 +383,10 @@ class Reference {
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);
- }
+ : data_(data),
+ parent_width_(parent_width),
+ byte_width_(static_cast<uint8_t>(1 << (packed_type & 3))),
+ type_(static_cast<Type>(packed_type >> 2)) {}
Type GetType() const { return type_; }
@@ -572,7 +574,23 @@ class Reference {
auto keys = m.Keys();
auto vals = m.Values();
for (size_t i = 0; i < keys.size(); i++) {
- keys[i].ToString(true, keys_quoted, s);
+ bool kq = keys_quoted;
+ if (!kq) {
+ // FlexBuffers keys may contain arbitrary characters, only allow
+ // unquoted if it looks like an "identifier":
+ const char *p = keys[i].AsKey();
+ if (!flatbuffers::is_alpha(*p) && *p != '_') {
+ kq = true;
+ } else {
+ while (*++p) {
+ if (!flatbuffers::is_alnum(*p) && *p != '_') {
+ kq = true;
+ break;
+ }
+ }
+ }
+ }
+ keys[i].ToString(true, kq, s);
s += ": ";
vals[i].ToString(true, keys_quoted, s);
if (i < keys.size() - 1) s += ", ";
@@ -756,6 +774,8 @@ class Reference {
return false;
}
+ friend class Verifier;
+
const uint8_t *data_;
uint8_t parent_width_;
uint8_t byte_width_;
@@ -850,6 +870,7 @@ inline Reference Map::operator[](const char *key) const {
case 2: comp = KeyCompare<uint16_t>; break;
case 4: comp = KeyCompare<uint32_t>; break;
case 8: comp = KeyCompare<uint64_t>; break;
+ default: FLATBUFFERS_ASSERT(false); return Reference();
}
auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
if (!res) return Reference(nullptr, 1, NullPackedType());
@@ -872,7 +893,7 @@ inline Reference GetRoot(const uint8_t *buffer, size_t size) {
}
inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
- return GetRoot(flatbuffers::vector_data(buffer), buffer.size());
+ return GetRoot(buffer.data(), buffer.size());
}
// Flags that configure how the Builder behaves.
@@ -1068,7 +1089,16 @@ class Builder FLATBUFFERS_FINAL_CLASS {
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);
+ return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
+ }
+
+ void Blob(const char *key, const void *data, size_t len) {
+ Key(key);
+ Blob(data, len);
+ }
+ void Blob(const char *key, const std::vector<uint8_t> &v) {
+ Key(key);
+ Blob(v);
}
// TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
@@ -1086,7 +1116,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
return stack_.size();
}
- // TODO(wvo): allow this to specify an aligment greater than the natural
+ // TODO(wvo): allow this to specify an alignment 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);
@@ -1121,27 +1151,24 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// 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;
- });
+ auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start);
+ std::sort(
+ dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool {
+ auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_);
+ auto bs = reinterpret_cast<const char *>(buf_.data() + 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.
@@ -1195,7 +1222,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Vector(elems, len);
}
template<typename T> void Vector(const std::vector<T> &vec) {
- Vector(flatbuffers::vector_data(vec), vec.size());
+ Vector(vec.data(), vec.size());
}
template<typename F> size_t TypedVector(F f) {
@@ -1397,12 +1424,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
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);
+ 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:
@@ -1552,9 +1577,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
}
}
}
- // If you get this assert, your fixed types are not one of:
+ // If you get this assert, your typed types are not one of:
// Int / UInt / Float / Key.
- FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type));
+ FLATBUFFERS_ASSERT(!typed || IsTypedVectorElementType(vector_type));
auto byte_width = Align(bit_width);
// Write vector. First the keys width/offset if available, and size.
if (keys) {
@@ -1597,10 +1622,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
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);
+ auto stra = reinterpret_cast<const char *>(buf_->data() + a);
+ auto strb = reinterpret_cast<const char *>(buf_->data() + b);
return strcmp(stra, strb) < 0;
}
const std::vector<uint8_t> *buf_;
@@ -1611,11 +1634,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
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;
+ auto stra = buf_->data() + a.first;
+ auto strb = buf_->data() + b.first;
+ auto cr = memcmp(stra, strb, (std::min)(a.second, b.second) + 1);
+ return cr < 0 || (cr == 0 && a.second < b.second);
}
const std::vector<uint8_t> *buf_;
};
@@ -1625,8 +1647,237 @@ class Builder FLATBUFFERS_FINAL_CLASS {
KeyOffsetMap key_pool;
StringOffsetMap string_pool;
+
+ friend class Verifier;
};
+// Helper class to verify the integrity of a FlexBuffer
+class Verifier FLATBUFFERS_FINAL_CLASS {
+ public:
+ Verifier(const uint8_t *buf, size_t buf_len,
+ // Supplying this vector likely results in faster verification
+ // of larger buffers with many shared keys/strings, but
+ // comes at the cost of using additional memory the same size of
+ // the buffer being verified, so it is by default off.
+ std::vector<uint8_t> *reuse_tracker = nullptr,
+ bool _check_alignment = true, size_t max_depth = 64)
+ : buf_(buf),
+ size_(buf_len),
+ depth_(0),
+ max_depth_(max_depth),
+ num_vectors_(0),
+ max_vectors_(buf_len),
+ check_alignment_(_check_alignment),
+ reuse_tracker_(reuse_tracker) {
+ FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
+ if (reuse_tracker_) {
+ reuse_tracker_->clear();
+ reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL));
+ }
+ }
+
+ private:
+ // Central location where any verification failures register.
+ bool Check(bool ok) const {
+ // clang-format off
+ #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
+ FLATBUFFERS_ASSERT(ok);
+ #endif
+ // clang-format on
+ return ok;
+ }
+
+ // Verify any range within the buffer.
+ bool VerifyFrom(size_t elem, size_t elem_len) const {
+ return Check(elem_len < size_ && elem <= size_ - elem_len);
+ }
+ bool VerifyBefore(size_t elem, size_t elem_len) const {
+ return Check(elem_len <= elem);
+ }
+
+ bool VerifyFromPointer(const uint8_t *p, size_t len) {
+ auto o = static_cast<size_t>(p - buf_);
+ return VerifyFrom(o, len);
+ }
+ bool VerifyBeforePointer(const uint8_t *p, size_t len) {
+ auto o = static_cast<size_t>(p - buf_);
+ return VerifyBefore(o, len);
+ }
+
+ bool VerifyByteWidth(size_t width) {
+ return Check(width == 1 || width == 2 || width == 4 || width == 8);
+ }
+
+ bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }
+
+ bool VerifyOffset(uint64_t off, const uint8_t *p) {
+ return Check(off <= static_cast<uint64_t>(size_)) &&
+ off <= static_cast<uint64_t>(p - buf_);
+ }
+
+ bool VerifyAlignment(const uint8_t *p, size_t size) const {
+ auto o = static_cast<size_t>(p - buf_);
+ return Check((o & (size - 1)) == 0 || !check_alignment_);
+ }
+
+// Macro, since we want to escape from parent function & use lazy args.
+#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \
+ if (reuse_tracker_) { \
+ auto packed_type = PACKED_TYPE; \
+ auto existing = (*reuse_tracker_)[P - buf_]; \
+ if (existing == packed_type) return true; \
+ /* Fail verification if already set with different type! */ \
+ if (!Check(existing == 0)) return false; \
+ (*reuse_tracker_)[P - buf_] = packed_type; \
+ }
+
+ bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) {
+ // Any kind of nesting goes thru this function, so guard against that
+ // here, both with simple nesting checks, and the reuse tracker if on.
+ depth_++;
+ num_vectors_++;
+ if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
+ return false;
+ auto size_byte_width = r.byte_width_;
+ if (!VerifyBeforePointer(p, size_byte_width)) return false;
+ FLEX_CHECK_VERIFIED(p - size_byte_width,
+ PackedType(Builder::WidthB(size_byte_width), r.type_));
+ auto sized = Sized(p, size_byte_width);
+ auto num_elems = sized.size();
+ auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
+ ? uint8_t(1)
+ : r.byte_width_;
+ auto max_elems = SIZE_MAX / elem_byte_width;
+ if (!Check(num_elems < max_elems))
+ return false; // Protect against byte_size overflowing.
+ auto byte_size = num_elems * elem_byte_width;
+ if (!VerifyFromPointer(p, byte_size)) return false;
+ if (elem_type == FBT_NULL) {
+ // Verify type bytes after the vector.
+ if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
+ auto v = Vector(p, size_byte_width);
+ for (size_t i = 0; i < num_elems; i++)
+ if (!VerifyRef(v[i])) return false;
+ } else if (elem_type == FBT_KEY) {
+ auto v = TypedVector(p, elem_byte_width, FBT_KEY);
+ for (size_t i = 0; i < num_elems; i++)
+ if (!VerifyRef(v[i])) return false;
+ } else {
+ FLATBUFFERS_ASSERT(IsInline(elem_type));
+ }
+ depth_--;
+ return true;
+ }
+
+ bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
+ // The vector part of the map has already been verified.
+ const size_t num_prefixed_fields = 3;
+ if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
+ p -= byte_width * num_prefixed_fields;
+ auto off = ReadUInt64(p, byte_width);
+ if (!VerifyOffset(off, p)) return false;
+ auto key_byte_with =
+ static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
+ if (!VerifyByteWidth(key_byte_with)) return false;
+ return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
+ p - off, FBT_KEY);
+ }
+
+ bool VerifyKey(const uint8_t *p) {
+ FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
+ while (p < buf_ + size_)
+ if (*p++) return true;
+ return false;
+ }
+
+#undef FLEX_CHECK_VERIFIED
+
+ bool VerifyTerminator(const String &s) {
+ return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
+ s.size() + 1);
+ }
+
+ bool VerifyRef(Reference r) {
+ // r.parent_width_ and r.data_ already verified.
+ if (!VerifyByteWidth(r.byte_width_) || !VerifyType(r.type_)) {
+ return false;
+ }
+ if (IsInline(r.type_)) {
+ // Inline scalars, don't require further verification.
+ return true;
+ }
+ // All remaining types are an offset.
+ auto off = ReadUInt64(r.data_, r.parent_width_);
+ if (!VerifyOffset(off, r.data_)) return false;
+ auto p = r.Indirect();
+ if (!VerifyAlignment(p, r.byte_width_)) return false;
+ switch (r.type_) {
+ case FBT_INDIRECT_INT:
+ case FBT_INDIRECT_UINT:
+ case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
+ case FBT_KEY: return VerifyKey(p);
+ case FBT_MAP:
+ return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
+ case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
+ case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
+ case FBT_VECTOR_BOOL:
+ case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
+ case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
+ case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
+ case FBT_VECTOR_STRING_DEPRECATED:
+ // Use of FBT_KEY here intentional, see elsewhere.
+ return VerifyVector(r, p, FBT_KEY);
+ case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
+ case FBT_STRING:
+ return VerifyVector(r, p, FBT_UINT) &&
+ VerifyTerminator(String(p, r.byte_width_));
+ case FBT_VECTOR_INT2:
+ case FBT_VECTOR_UINT2:
+ case FBT_VECTOR_FLOAT2:
+ case FBT_VECTOR_INT3:
+ case FBT_VECTOR_UINT3:
+ case FBT_VECTOR_FLOAT3:
+ case FBT_VECTOR_INT4:
+ case FBT_VECTOR_UINT4:
+ case FBT_VECTOR_FLOAT4: {
+ uint8_t len = 0;
+ auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
+ if (!VerifyType(vtype)) return false;
+ return VerifyFromPointer(p, static_cast<size_t>(r.byte_width_) * len);
+ }
+ default: return false;
+ }
+ }
+
+ public:
+ bool VerifyBuffer() {
+ if (!Check(size_ >= 3)) return false;
+ auto end = buf_ + size_;
+ auto byte_width = *--end;
+ auto packed_type = *--end;
+ return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
+ VerifyRef(Reference(end - byte_width, byte_width, packed_type));
+ }
+
+ private:
+ const uint8_t *buf_;
+ size_t size_;
+ size_t depth_;
+ const size_t max_depth_;
+ size_t num_vectors_;
+ const size_t max_vectors_;
+ bool check_alignment_;
+ std::vector<uint8_t> *reuse_tracker_;
+};
+
+// Utility function that constructs the Verifier for you, see above for
+// parameters.
+inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
+ std::vector<uint8_t> *reuse_tracker = nullptr) {
+ Verifier verifier(buf, buf_len, reuse_tracker);
+ return verifier.VerifyBuffer();
+}
+
} // namespace flexbuffers
#if defined(_MSC_VER)
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/idl.h b/contrib/libs/flatbuffers/include/flatbuffers/idl.h
index a82ff8a694..1c07254ac3 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/idl.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/idl.h
@@ -17,6 +17,8 @@
#ifndef FLATBUFFERS_IDL_H_
#define FLATBUFFERS_IDL_H_
+#include <algorithm>
+#include <functional>
#include <map>
#include <memory>
#include <stack>
@@ -27,10 +29,6 @@
#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.
@@ -47,26 +45,27 @@ namespace flatbuffers {
// 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 */
+ TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 0) \
+ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 1) /* begin scalar/int */ \
+ TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool, 2) \
+ TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8, 3) \
+ TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8, 4) \
+ TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16, 5) \
+ TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16, 6) \
+ TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32, 7) \
+ TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32, 8) \
+ TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64, 9) \
+ TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64, 10) /* end int */ \
+ TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32, 11) /* begin float */ \
+ TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double, 12) /* 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>)
+ TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>, 13) \
+ TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 14) \
+ TD(VECTOR64, "", Offset64<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>, 18) \
+ TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 15) \
+ TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>, 16)
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
- TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
+ TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>, 17)
// The fields are:
// - enum
// - FlatBuffers schema type.
@@ -75,15 +74,17 @@ namespace flatbuffers {
// - Go type.
// - C# / .Net type.
// - Python type.
-// - Rust type.
// - Kotlin type.
+// - Rust type.
+// - Swift type.
+// - enum value (matches the reflected values)
// 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) \
+ RTYPE, KTYPE, STYPE, ...) \
case BASE_TYPE_ ## ENUM: \
// do something specific to CTYPE here
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
@@ -115,8 +116,9 @@ switch (type) {
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
#endif
enum BaseType {
- #define FLATBUFFERS_TD(ENUM, ...) \
- BASE_TYPE_ ## ENUM,
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE, ENUM_VALUE) \
+ BASE_TYPE_ ## ENUM = ENUM_VALUE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
@@ -138,6 +140,8 @@ inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
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 IsVector (BaseType t) { return t == BASE_TYPE_VECTOR ||
+ t == BASE_TYPE_VECTOR64; }
inline bool IsUnsigned(BaseType t) {
return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
@@ -145,12 +149,40 @@ inline bool IsUnsigned(BaseType t) {
(t == BASE_TYPE_ULONG);
}
-// clang-format on
+inline size_t SizeOf(const BaseType t) {
+ switch (t) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: return sizeof(CTYPE);
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ return 0;
+}
-extern const char *const kTypeNames[];
-extern const char kTypeSizes[];
+inline const char* TypeName(const BaseType t) {
+ switch (t) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
+ case BASE_TYPE_##ENUM: return IDLTYPE;
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ return nullptr;
+}
+
+inline const char* StringOf(const BaseType t) {
+ switch (t) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: return #CTYPE;
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ return "";
+}
-inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
+// clang-format on
struct StructDef;
struct EnumDef;
@@ -167,7 +199,7 @@ struct Type {
enum_def(_ed),
fixed_length(_fixed_length) {}
- bool operator==(const Type &o) {
+ bool operator==(const Type &o) const {
return base_type == o.base_type && element == o.element &&
struct_def == o.struct_def && enum_def == o.enum_def;
}
@@ -181,7 +213,8 @@ struct Type {
bool Deserialize(const Parser &parser, const reflection::Type *type);
BaseType base_type;
- BaseType element; // only set if t == BASE_TYPE_VECTOR
+ BaseType element; // only set if t == BASE_TYPE_VECTOR or
+ // BASE_TYPE_VECTOR64
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.
@@ -207,7 +240,7 @@ template<typename T> class SymbolTable {
}
bool Add(const std::string &name, T *e) {
- vector_emplace_back(&vec, e);
+ vec.emplace_back(e);
auto it = dict.find(name);
if (it != dict.end()) return true;
dict[name] = e;
@@ -266,7 +299,8 @@ struct Definition {
defined_namespace(nullptr),
serialized_location(0),
index(-1),
- refcount(1) {}
+ refcount(1),
+ declaration_file(nullptr) {}
flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
@@ -286,6 +320,7 @@ struct Definition {
uoffset_t serialized_location;
int index; // Inside the vector it is stored.
int refcount;
+ const std::string *declaration_file;
};
struct FieldDef : public Definition {
@@ -295,9 +330,11 @@ struct FieldDef : public Definition {
shared(false),
native_inline(false),
flexbuffer(false),
+ offset64(false),
presence(kDefault),
- nested_flatbuffer(NULL),
- padding(0) {}
+ nested_flatbuffer(nullptr),
+ padding(0),
+ sibling_union_field(nullptr) {}
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
const Parser &parser) const;
@@ -307,15 +344,9 @@ struct FieldDef : public Definition {
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;
- }
+ 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.
@@ -326,6 +357,7 @@ struct FieldDef : public Definition {
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.
+ bool offset64; // If the field uses 64-bit offsets.
enum Presence {
// Field must always be present.
@@ -348,6 +380,12 @@ struct FieldDef : public Definition {
StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
size_t padding; // Bytes to always pad after this field.
+
+ // sibling_union_field is always set to nullptr. The only exception is
+ // when FieldDef is a union field or an union type field. Therefore,
+ // sibling_union_field on a union field points to the union type field
+ // and vice-versa.
+ FieldDef *sibling_union_field;
};
struct StructDef : public Definition {
@@ -380,6 +418,7 @@ struct StructDef : public Definition {
size_t bytesize; // Size if fixed.
flatbuffers::unique_ptr<std::string> original_location;
+ std::vector<voffset_t> reserved_ids;
};
struct EnumDef;
@@ -389,7 +428,14 @@ struct EnumVal {
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
- bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
+ bool Deserialize(Parser &parser, const reflection::EnumVal *val);
+
+ 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);
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
int64_t GetAsInt64() const { return value; }
@@ -399,6 +445,7 @@ struct EnumVal {
std::string name;
std::vector<std::string> doc_comment;
Type union_type;
+ SymbolTable<Value> attributes;
private:
friend EnumDef;
@@ -471,12 +518,30 @@ inline bool IsStruct(const Type &type) {
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
}
+inline bool IsIncompleteStruct(const Type &type) {
+ return type.base_type == BASE_TYPE_STRUCT && type.struct_def->predecl;
+}
+
+inline bool IsTable(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 IsUnionType(const Type &type) {
+ return IsUnion(type) && IsInteger(type.base_type);
+}
+
+inline bool IsVector(const Type &type) { return IsVector(type.base_type); }
+
+inline bool IsVectorOfStruct(const Type &type) {
+ return IsVector(type) && IsStruct(type.VectorType());
+}
+
+inline bool IsVectorOfTable(const Type &type) {
+ return IsVector(type) && IsTable(type.VectorType());
}
inline bool IsArray(const Type &type) {
@@ -519,8 +584,11 @@ inline bool operator!=(const EnumVal &lhs, const EnumVal &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);
+ (a.struct_def != nullptr && b.struct_def != nullptr &&
+ a.struct_def->name == b.struct_def->name)) &&
+ (a.enum_def == b.enum_def ||
+ (a.enum_def != nullptr && b.enum_def != nullptr &&
+ a.enum_def->name == b.enum_def->name));
}
struct RPCCall : public Definition {
@@ -540,17 +608,41 @@ struct ServiceDef : public Definition {
SymbolTable<RPCCall> calls;
};
+struct IncludedFile {
+ // The name of the schema file being included, as defined in the .fbs file.
+ // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this
+ // value is "foo/bar/baz.fbs").
+ std::string schema_name;
+
+ // The filename of where the included file was found, after searching the
+ // relative paths plus any other paths included with `flatc -I ...`. Note,
+ // while this is sometimes the same as schema_name, it is not always, since it
+ // can be defined relative to where flatc was invoked.
+ std::string filename;
+};
+
+// Since IncludedFile is contained within a std::set, need to provide ordering.
+inline bool operator<(const IncludedFile &a, const IncludedFile &b) {
+ return a.filename < b.filename;
+}
+
// Container of options that may apply to any of the source/text generators.
struct IDLOptions {
+ // field case style options for C++
+ enum CaseStyle { CaseStyle_Unchanged = 0, CaseStyle_Upper, CaseStyle_Lower };
+ enum class ProtoIdGapAction { NO_OP, WARNING, ERROR };
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 cpp_minify_enums;
bool output_enum_identifiers;
bool prefixed_enums;
bool scoped_enums;
+ bool emit_min_max_enum_values;
+ bool swift_implementation_only;
bool include_dependence_headers;
bool mutable_buffer;
bool one_file;
@@ -564,22 +656,26 @@ struct IDLOptions {
std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type;
bool cpp_object_api_string_flexible_constructor;
+ CaseStyle cpp_object_api_field_case_style;
bool cpp_direct_copy;
bool gen_nullable;
+ std::string java_package_prefix;
bool java_checkerframework;
bool gen_generated;
+ bool gen_json_coders;
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 keep_prefix;
bool binary_schema_comments;
bool binary_schema_builtins;
bool binary_schema_gen_embed;
std::string go_import;
std::string go_namespace;
+ std::string go_module_name;
bool protobuf_ascii_alike;
bool size_prefixed;
std::string root_type;
@@ -593,6 +689,21 @@ struct IDLOptions {
std::string filename_suffix;
std::string filename_extension;
bool no_warnings;
+ bool warnings_as_errors;
+ std::string project_root;
+ bool cs_global_alias;
+ bool json_nested_flatbuffers;
+ bool json_nested_flexbuffers;
+ bool json_nested_legacy_flatbuffers;
+ bool ts_flat_files;
+ bool ts_entry_points;
+ bool ts_no_import_ext;
+ bool no_leak_private_annotations;
+ bool require_json_eof;
+ bool keep_proto_id;
+ bool python_no_type_prefix_suffix;
+ bool python_typing;
+ ProtoIdGapAction proto_id_gap_action;
// Possible options for the more general generator below.
enum Language {
@@ -613,11 +724,11 @@ struct IDLOptions {
kKotlin = 1 << 15,
kSwift = 1 << 16,
kCppYandexMapsIter = 1 << 17,
+ kNim = 1 << 17,
+ kProto = 1 << 18,
kMAX
};
- Language lang;
-
enum MiniReflect { kNone, kTypes, kTypesAndNames };
MiniReflect mini_reflect;
@@ -625,6 +736,12 @@ struct IDLOptions {
// If set, require all fields in a table to be explicitly numbered.
bool require_explicit_ids;
+ // If set, implement serde::Serialize for generated Rust types
+ bool rust_serialize;
+
+ // If set, generate rust types in individual files with a root module file.
+ bool rust_module_root_file;
+
// The corresponding language bit will be set if a language is included
// for code generation.
unsigned long lang_to_generate;
@@ -643,9 +760,12 @@ struct IDLOptions {
strict_json(false),
output_default_scalars_in_json(false),
indent_step(2),
+ cpp_minify_enums(false),
output_enum_identifiers(true),
prefixed_enums(true),
scoped_enums(false),
+ emit_min_max_enum_values(true),
+ swift_implementation_only(false),
include_dependence_headers(true),
mutable_buffer(false),
one_file(false),
@@ -658,15 +778,17 @@ struct IDLOptions {
gen_compare(false),
cpp_object_api_pointer_type("std::unique_ptr"),
cpp_object_api_string_flexible_constructor(false),
+ cpp_object_api_field_case_style(CaseStyle_Unchanged),
cpp_direct_copy(true),
gen_nullable(false),
java_checkerframework(false),
gen_generated(false),
+ gen_json_coders(false),
object_suffix("T"),
union_value_namespacing(true),
allow_non_utf8(false),
natural_utf8(false),
- keep_include_path(false),
+ keep_prefix(false),
binary_schema_comments(false),
binary_schema_builtins(false),
binary_schema_gen_embed(false),
@@ -679,9 +801,25 @@ struct IDLOptions {
filename_suffix("_generated"),
filename_extension(),
no_warnings(false),
- lang(IDLOptions::kJava),
+ warnings_as_errors(false),
+ project_root(""),
+ cs_global_alias(false),
+ json_nested_flatbuffers(true),
+ json_nested_flexbuffers(true),
+ json_nested_legacy_flatbuffers(false),
+ ts_flat_files(false),
+ ts_entry_points(false),
+ ts_no_import_ext(false),
+ no_leak_private_annotations(false),
+ require_json_eof(true),
+ keep_proto_id(false),
+ python_no_type_prefix_suffix(false),
+ python_typing(false),
+ proto_id_gap_action(ProtoIdGapAction::WARNING),
mini_reflect(IDLOptions::kNone),
require_explicit_ids(false),
+ rust_serialize(false),
+ rust_module_root_file(false),
lang_to_generate(0),
set_empty_strings_to_null(true),
set_empty_vectors_to_null(true) {}
@@ -690,7 +828,8 @@ struct IDLOptions {
// This encapsulates where the parser is in the current source file.
struct ParserState {
ParserState()
- : cursor_(nullptr),
+ : prev_cursor_(nullptr),
+ cursor_(nullptr),
line_start_(nullptr),
line_(0),
token_(-1),
@@ -698,6 +837,7 @@ struct ParserState {
protected:
void ResetState(const char *source) {
+ prev_cursor_ = source;
cursor_ = source;
line_ = 0;
MarkNewLine();
@@ -713,6 +853,7 @@ struct ParserState {
return static_cast<int64_t>(cursor_ - line_start_);
}
+ const char *prev_cursor_;
const char *cursor_;
const char *line_start_;
int line_; // the current line being parsed
@@ -781,6 +922,7 @@ class Parser : public ParserState {
root_struct_def_(nullptr),
opts(options),
uses_flexbuffers_(false),
+ has_warning_(false),
advanced_features_(0),
source_(nullptr),
anonymous_counter_(0),
@@ -815,8 +957,22 @@ class Parser : public ParserState {
known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true;
known_attributes_["private"] = true;
+
+ // An attribute added to a field to indicate that is uses 64-bit addressing.
+ known_attributes_["offset64"] = true;
+
+ // An attribute added to a vector field to indicate that it uses 64-bit
+ // addressing and it has a 64-bit length.
+ known_attributes_["vector64"] = true;
}
+ // Copying is not allowed
+ Parser(const Parser &) = delete;
+ Parser &operator=(const Parser &) = delete;
+
+ Parser(Parser &&) = default;
+ Parser &operator=(Parser &&) = default;
+
~Parser() {
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
delete *it;
@@ -839,6 +995,9 @@ class Parser : public ParserState {
bool ParseJson(const char *json, const char *json_filename = nullptr);
+ // Returns the number of characters were consumed when parsing a JSON string.
+ std::ptrdiff_t BytesConsumed() const;
+
// Set the root type. May override the one set in the schema.
bool SetRootType(const char *name);
@@ -884,6 +1043,11 @@ class Parser : public ParserState {
// @param opts Options used to parce a schema and generate code.
static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
+ // Get the set of included files that are directly referenced by the file
+ // being parsed. This does not include files that are transitively included by
+ // others includes.
+ std::vector<IncludedFile> GetIncludedFiles() const;
+
private:
class ParseDepthGuard;
@@ -910,7 +1074,7 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def,
- uoffset_t count,
+ size_t count,
bool inside_vector = false);
template<typename F>
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
@@ -922,7 +1086,7 @@ class Parser : public ParserState {
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 ParseVectorDelimiters(size_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);
@@ -943,16 +1107,18 @@ class Parser : public ParserState {
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 ParseEnum(bool is_union, EnumDef **dest,
+ const char *filename);
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 ParseDecl(const char *filename);
+ FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename);
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
bool isextend, bool inside_oneof);
+ FLATBUFFERS_CHECKED_ERROR ParseProtoMapField(StructDef *struct_def);
FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
@@ -967,6 +1133,9 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
const char **include_paths,
const char *source_filename);
+ FLATBUFFERS_CHECKED_ERROR CheckPrivateLeak();
+ FLATBUFFERS_CHECKED_ERROR CheckPrivatelyLeakedFields(
+ const Definition &def, const Definition &value_type);
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
const char **include_paths,
const char *source_filename,
@@ -982,11 +1151,14 @@ class Parser : public ParserState {
bool SupportsAdvancedArrayFeatures() const;
bool SupportsOptionalScalars() const;
bool SupportsDefaultVectorsAndStrings() const;
+ bool Supports64BitOffsets() const;
Namespace *UniqueNamespace(Namespace *ns);
FLATBUFFERS_CHECKED_ERROR RecurseError();
template<typename F> CheckedError Recurse(F f);
+ const std::string &GetPooledString(const std::string &s) const;
+
public:
SymbolTable<Type> types_;
SymbolTable<StructDef> structs_;
@@ -1005,33 +1177,34 @@ class Parser : public ParserState {
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::map<std::string, std::set<IncludedFile>> files_included_per_file_;
std::vector<std::string> native_included_files_;
std::map<std::string, bool> known_attributes_;
IDLOptions opts;
bool uses_flexbuffers_;
+ bool has_warning_;
uint64_t advanced_features_;
+ std::string file_being_parsed_;
+
private:
const char *source_;
- std::string file_being_parsed_;
-
std::vector<std::pair<Value, FieldDef *>> field_stack_;
+ // TODO(cneo): Refactor parser to use string_cache more often to save
+ // on memory usage.
+ mutable std::set<std::string> string_cache_;
+
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,
@@ -1040,13 +1213,14 @@ extern std::string MakeScreamingCamel(const std::string &in);
// 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);
+extern const char *GenerateTextFromTable(const Parser &parser, const void *table,
+ const std::string &tablename,
+ std::string *text);
+extern const char *GenerateText(const Parser &parser, const void *flatbuffer,
+ std::string *text);
+extern const char *GenerateTextFile(const Parser &parser,
+ const std::string &path,
+ const std::string &file_name);
// Generate Json schema to string
// See idl_gen_json_schema.cpp.
@@ -1127,9 +1301,9 @@ extern bool GenerateSwift(const Parser &parser, const std::string &path,
// 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);
+ const std::string &file_name, bool no_log);
extern bool GenerateFBS(const Parser &parser, const std::string &path,
- const std::string &file_name);
+ const std::string &file_name, bool no_log);
// Generate a C++ header for reading with templated file iterator from
// the definitions in the Parser object.
@@ -1162,9 +1336,10 @@ extern std::string RustMakeRule(const Parser &parser, const std::string &path,
// 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);
+extern std::string CSharpMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+extern std::string JavaMakeRule(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.
@@ -1203,6 +1378,9 @@ extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
const std::string &file_name);
+
+extern bool GenerateRustModuleRootFile(const Parser &parser,
+ const std::string &path);
} // namespace flatbuffers
#endif // FLATBUFFERS_IDL_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h
index d268a3ffea..188c2ec4ca 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/reflection.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h
@@ -21,7 +21,7 @@
// 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
+// See scripts/generate_code.py for generation.
#include "reflection_generated.h"
// Helper functionality for reflection.
@@ -66,6 +66,7 @@ inline size_t GetTypeSize(reflection::BaseType base_type) {
4, // Union
0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
// errors.
+ 8, // Vector64
0 // MaxBaseType. This must be kept the last entry in this array.
};
@@ -88,13 +89,22 @@ inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
}
// Get the root, regardless of what type it is.
-inline Table *GetAnyRoot(uint8_t *flatbuf) {
+inline Table *GetAnyRoot(uint8_t *const flatbuf) {
return GetMutableRoot<Table>(flatbuf);
}
-inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
+
+inline const Table *GetAnyRoot(const uint8_t *const flatbuf) {
return GetRoot<Table>(flatbuf);
}
+inline Table *GetAnySizePrefixedRoot(uint8_t *const flatbuf) {
+ return GetMutableSizePrefixedRoot<Table>(flatbuf);
+}
+
+inline const Table *GetAnySizePrefixedRoot(const uint8_t *const flatbuf) {
+ return GetSizePrefixedRoot<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()));
@@ -279,6 +289,12 @@ T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
}
+// Loop over all the fields of the provided `object` and call `func` on each one
+// in increasing order by their field->id(). If `reverse` is true, `func` is
+// called in descending order
+void ForAllFields(const reflection::Object *object, bool reverse,
+ std::function<void(const reflection::Field *)> func);
+
// ------------------------- SETTERS -------------------------
// Set any scalar field, if you know its exact type.
@@ -379,12 +395,12 @@ 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))),
+ reinterpret_cast<uint8_t *>(vec.data())),
vec_(vec) {}
T *operator*() const {
- return reinterpret_cast<T *>(
- reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
+ return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(vec_.data()) +
+ offset_);
}
T *operator->() const { return operator*(); }
@@ -412,7 +428,7 @@ inline const reflection::Object &GetUnionType(
FLATBUFFERS_ASSERT(type_field);
auto union_type = GetFieldI<uint8_t>(table, *type_field);
auto enumval = enumdef->values()->LookupByKey(union_type);
- return *enumval->object();
+ return *schema.objects()->Get(enumval->union_type()->index());
}
// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
@@ -497,6 +513,11 @@ 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);
+bool VerifySizePrefixed(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
index 93dc4b88b7..067222d9dc 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h
@@ -6,6 +6,13 @@
#include "flatbuffers.h"
+// Ensure the included flatbuffers.h is the same version as when this file was
+// generated, otherwise it may not be compatible.
+static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
+ FLATBUFFERS_VERSION_MINOR == 5 &&
+ FLATBUFFERS_VERSION_REVISION == 9,
+ "Non-compatible flatbuffers version included");
+
namespace reflection {
struct Type;
@@ -32,6 +39,9 @@ struct RPCCallBuilder;
struct Service;
struct ServiceBuilder;
+struct SchemaFile;
+struct SchemaFileBuilder;
+
struct Schema;
struct SchemaBuilder;
@@ -54,10 +64,11 @@ enum BaseType {
Obj = 15,
Union = 16,
Array = 17,
- MaxBaseType = 18
+ Vector64 = 18,
+ MaxBaseType = 19
};
-inline const BaseType (&EnumValuesBaseType())[19] {
+inline const BaseType (&EnumValuesBaseType())[20] {
static const BaseType values[] = {
None,
UType,
@@ -77,13 +88,14 @@ inline const BaseType (&EnumValuesBaseType())[19] {
Obj,
Union,
Array,
+ Vector64,
MaxBaseType
};
return values;
}
inline const char * const *EnumNamesBaseType() {
- static const char * const names[20] = {
+ static const char * const names[21] = {
"None",
"UType",
"Bool",
@@ -102,6 +114,7 @@ inline const char * const *EnumNamesBaseType() {
"Obj",
"Union",
"Array",
+ "Vector64",
"MaxBaseType",
nullptr
};
@@ -109,11 +122,12 @@ inline const char * const *EnumNamesBaseType() {
}
inline const char *EnumNameBaseType(BaseType e) {
- if (flatbuffers::IsOutRange(e, None, MaxBaseType)) return "";
+ if (::flatbuffers::IsOutRange(e, None, MaxBaseType)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesBaseType()[index];
}
+/// New schema language features that are not supported by old code generators.
enum AdvancedFeatures {
AdvancedArrayFeatures = 1ULL,
AdvancedUnionFeatures = 2ULL,
@@ -147,18 +161,20 @@ inline const char * const *EnumNamesAdvancedFeatures() {
}
inline const char *EnumNameAdvancedFeatures(AdvancedFeatures e) {
- if (flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings)) return "";
+ 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 {
+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
+ VT_FIXED_LENGTH = 10,
+ VT_BASE_SIZE = 12,
+ VT_ELEMENT_SIZE = 14
};
reflection::BaseType base_type() const {
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
@@ -172,20 +188,30 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
uint16_t fixed_length() const {
return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ /// The size (octets) of the `base_type` field.
+ uint32_t base_size() const {
+ return GetField<uint32_t>(VT_BASE_SIZE, 4);
+ }
+ /// The size (octets) of the `element` field, if present.
+ uint32_t element_size() const {
+ return GetField<uint32_t>(VT_ELEMENT_SIZE, 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) &&
+ VerifyField<int8_t>(verifier, VT_BASE_TYPE, 1) &&
+ VerifyField<int8_t>(verifier, VT_ELEMENT, 1) &&
+ VerifyField<int32_t>(verifier, VT_INDEX, 4) &&
+ VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH, 2) &&
+ VerifyField<uint32_t>(verifier, VT_BASE_SIZE, 4) &&
+ VerifyField<uint32_t>(verifier, VT_ELEMENT_SIZE, 4) &&
verifier.EndTable();
}
};
struct TypeBuilder {
typedef Type Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
+ ::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);
}
@@ -198,24 +224,34 @@ struct TypeBuilder {
void add_fixed_length(uint16_t fixed_length) {
fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
}
- explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ void add_base_size(uint32_t base_size) {
+ fbb_.AddElement<uint32_t>(Type::VT_BASE_SIZE, base_size, 4);
+ }
+ void add_element_size(uint32_t element_size) {
+ fbb_.AddElement<uint32_t>(Type::VT_ELEMENT_SIZE, element_size, 0);
+ }
+ explicit TypeBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Type> Finish() {
+ ::flatbuffers::Offset<Type> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Type>(end);
+ auto o = ::flatbuffers::Offset<Type>(end);
return o;
}
};
-inline flatbuffers::Offset<Type> CreateType(
- flatbuffers::FlatBufferBuilder &_fbb,
+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) {
+ uint16_t fixed_length = 0,
+ uint32_t base_size = 4,
+ uint32_t element_size = 0) {
TypeBuilder builder_(_fbb);
+ builder_.add_element_size(element_size);
+ builder_.add_base_size(base_size);
builder_.add_index(index);
builder_.add_fixed_length(fixed_length);
builder_.add_element(element);
@@ -223,25 +259,25 @@ inline flatbuffers::Offset<Type> CreateType(
return builder_.Finish();
}
-struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+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 *key() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_KEY);
}
- bool KeyCompareLessThan(const KeyValue *o) const {
+ bool KeyCompareLessThan(const KeyValue * const o) const {
return *key() < *o->key();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(key()->c_str(), val);
+ int KeyCompareWithValue(const char *_key) const {
+ return strcmp(key()->c_str(), _key);
}
- const flatbuffers::String *value() const {
- return GetPointer<const flatbuffers::String *>(VT_VALUE);
+ const ::flatbuffers::String *value() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_VALUE);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_KEY) &&
verifier.VerifyString(key()) &&
@@ -253,38 +289,38 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct KeyValueBuilder {
typedef KeyValue Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_key(flatbuffers::Offset<flatbuffers::String> key) {
+ ::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) {
+ void add_value(::flatbuffers::Offset<::flatbuffers::String> value) {
fbb_.AddOffset(KeyValue::VT_VALUE, value);
}
- explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ explicit KeyValueBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<KeyValue> Finish() {
+ ::flatbuffers::Offset<KeyValue> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<KeyValue>(end);
+ 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) {
+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,
+inline ::flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
const char *key = nullptr,
const char *value = nullptr) {
auto key__ = key ? _fbb.CreateString(key) : 0;
@@ -295,118 +331,120 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
value__);
}
-struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+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
+ VT_DOCUMENTATION = 12,
+ VT_ATTRIBUTES = 14
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ 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 {
+ bool KeyCompareLessThan(const EnumVal * const 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);
+ int KeyCompareWithValue(int64_t _value) const {
+ return static_cast<int>(value() > _value) - static_cast<int>(value() < _value);
}
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);
+ const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation() const {
+ return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ 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()) &&
+ VerifyField<int64_t>(verifier, VT_VALUE, 8) &&
VerifyOffset(verifier, VT_UNION_TYPE) &&
verifier.VerifyTable(union_type()) &&
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.VerifyVector(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
verifier.EndTable();
}
};
struct EnumValBuilder {
typedef EnumVal Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ 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) {
+ void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
}
- explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ void add_attributes(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(EnumVal::VT_ATTRIBUTES, attributes);
+ }
+ explicit EnumValBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<EnumVal> Finish() {
+ ::flatbuffers::Offset<EnumVal> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<EnumVal>(end);
+ 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,
+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) {
+ ::flatbuffers::Offset<reflection::Type> union_type = 0,
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0) {
EnumValBuilder builder_(_fbb);
builder_.add_value(value);
+ builder_.add_attributes(attributes);
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,
+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) {
+ ::flatbuffers::Offset<reflection::Type> union_type = 0,
+ const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
+ std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
- auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
return reflection::CreateEnumVal(
_fbb,
name__,
value,
- object,
union_type,
- documentation__);
+ documentation__,
+ attributes__);
}
-struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+struct Enum FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef EnumBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
@@ -414,19 +452,20 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_IS_UNION = 8,
VT_UNDERLYING_TYPE = 10,
VT_ATTRIBUTES = 12,
- VT_DOCUMENTATION = 14
+ VT_DOCUMENTATION = 14,
+ VT_DECLARATION_FILE = 16
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ const ::flatbuffers::String *name() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_NAME);
}
- bool KeyCompareLessThan(const Enum *o) const {
+ bool KeyCompareLessThan(const Enum * const o) const {
return *name() < *o->name();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(name()->c_str(), val);
+ int KeyCompareWithValue(const char *_name) const {
+ return strcmp(name()->c_str(), _name);
}
- const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *>(VT_VALUES);
+ 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;
@@ -434,20 +473,24 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
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<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);
}
- const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ /// File that this Enum is declared in.
+ const ::flatbuffers::String *declaration_file() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ 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) &&
+ VerifyField<uint8_t>(verifier, VT_IS_UNION, 1) &&
VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
verifier.VerifyTable(underlying_type()) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
@@ -456,39 +499,44 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.VerifyVector(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyOffset(verifier, VT_DECLARATION_FILE) &&
+ verifier.VerifyString(declaration_file()) &&
verifier.EndTable();
}
};
struct EnumBuilder {
typedef Enum Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ 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) {
+ 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) {
+ 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) {
+ void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
}
- explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
+ fbb_.AddOffset(Enum::VT_DECLARATION_FILE, declaration_file);
+ }
+ explicit EnumBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Enum> Finish() {
+ ::flatbuffers::Offset<Enum> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Enum>(end);
+ 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);
@@ -496,15 +544,17 @@ struct EnumBuilder {
}
};
-inline flatbuffers::Offset<Enum> CreateEnum(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::String> name = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0,
+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) {
+ ::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,
+ ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
EnumBuilder builder_(_fbb);
+ builder_.add_declaration_file(declaration_file);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_underlying_type(underlying_type);
@@ -514,18 +564,20 @@ inline flatbuffers::Offset<Enum> CreateEnum(
return builder_.Finish();
}
-inline flatbuffers::Offset<Enum> CreateEnumDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
+inline ::flatbuffers::Offset<Enum> CreateEnumDirect(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
- std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = 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) {
+ ::flatbuffers::Offset<reflection::Type> underlying_type = 0,
+ std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
+ const char *declaration_file = 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;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
+ auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
return reflection::CreateEnum(
_fbb,
name__,
@@ -533,10 +585,11 @@ inline flatbuffers::Offset<Enum> CreateEnumDirect(
is_union,
underlying_type,
attributes__,
- documentation__);
+ documentation__,
+ declaration_file__);
}
-struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+struct Field FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef FieldBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
@@ -550,16 +603,18 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_KEY = 20,
VT_ATTRIBUTES = 22,
VT_DOCUMENTATION = 24,
- VT_OPTIONAL = 26
+ VT_OPTIONAL = 26,
+ VT_PADDING = 28,
+ VT_OFFSET64 = 30
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ const ::flatbuffers::String *name() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_NAME);
}
- bool KeyCompareLessThan(const Field *o) const {
+ bool KeyCompareLessThan(const Field * const o) const {
return *name() < *o->name();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(name()->c_str(), val);
+ int KeyCompareWithValue(const char *_name) const {
+ return strcmp(name()->c_str(), _name);
}
const reflection::Type *type() const {
return GetPointer<const reflection::Type *>(VT_TYPE);
@@ -585,47 +640,57 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
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<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);
+ 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 {
+ /// Number of padding octets to always add after this field. Structs only.
+ uint16_t padding() const {
+ return GetField<uint16_t>(VT_PADDING, 0);
+ }
+ /// If the field uses 64-bit offsets.
+ bool offset64() const {
+ return GetField<uint8_t>(VT_OFFSET64, 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) &&
+ VerifyField<uint16_t>(verifier, VT_ID, 2) &&
+ VerifyField<uint16_t>(verifier, VT_OFFSET, 2) &&
+ VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER, 8) &&
+ VerifyField<double>(verifier, VT_DEFAULT_REAL, 8) &&
+ VerifyField<uint8_t>(verifier, VT_DEPRECATED, 1) &&
+ VerifyField<uint8_t>(verifier, VT_REQUIRED, 1) &&
+ VerifyField<uint8_t>(verifier, VT_KEY, 1) &&
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) &&
+ VerifyField<uint8_t>(verifier, VT_OPTIONAL, 1) &&
+ VerifyField<uint16_t>(verifier, VT_PADDING, 2) &&
+ VerifyField<uint8_t>(verifier, VT_OFFSET64, 1) &&
verifier.EndTable();
}
};
struct FieldBuilder {
typedef Field Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ void add_type(::flatbuffers::Offset<reflection::Type> type) {
fbb_.AddOffset(Field::VT_TYPE, type);
}
void add_id(uint16_t id) {
@@ -649,32 +714,38 @@ struct FieldBuilder {
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) {
+ 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) {
+ 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)
+ void add_padding(uint16_t padding) {
+ fbb_.AddElement<uint16_t>(Field::VT_PADDING, padding, 0);
+ }
+ void add_offset64(bool offset64) {
+ fbb_.AddElement<uint8_t>(Field::VT_OFFSET64, static_cast<uint8_t>(offset64), 0);
+ }
+ explicit FieldBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Field> Finish() {
+ ::flatbuffers::Offset<Field> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Field>(end);
+ 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,
+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,
@@ -682,9 +753,11 @@ inline flatbuffers::Offset<Field> CreateField(
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) {
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
+ bool optional = false,
+ uint16_t padding = 0,
+ bool offset64 = false) {
FieldBuilder builder_(_fbb);
builder_.add_default_real(default_real);
builder_.add_default_integer(default_integer);
@@ -692,8 +765,10 @@ inline flatbuffers::Offset<Field> CreateField(
builder_.add_attributes(attributes);
builder_.add_type(type);
builder_.add_name(name);
+ builder_.add_padding(padding);
builder_.add_offset(offset);
builder_.add_id(id);
+ builder_.add_offset64(offset64);
builder_.add_optional(optional);
builder_.add_key(key);
builder_.add_required(required);
@@ -701,10 +776,10 @@ inline flatbuffers::Offset<Field> CreateField(
return builder_.Finish();
}
-inline flatbuffers::Offset<Field> CreateFieldDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
+inline ::flatbuffers::Offset<Field> CreateFieldDirect(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
- flatbuffers::Offset<reflection::Type> type = 0,
+ ::flatbuffers::Offset<reflection::Type> type = 0,
uint16_t id = 0,
uint16_t offset = 0,
int64_t default_integer = 0,
@@ -712,12 +787,14 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
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) {
+ std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
+ bool optional = false,
+ uint16_t padding = 0,
+ bool offset64 = 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;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
return reflection::CreateField(
_fbb,
name__,
@@ -731,10 +808,12 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
key,
attributes__,
documentation__,
- optional);
+ optional,
+ padding,
+ offset64);
}
-struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+struct Object FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef ObjectBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
@@ -743,19 +822,20 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_MINALIGN = 10,
VT_BYTESIZE = 12,
VT_ATTRIBUTES = 14,
- VT_DOCUMENTATION = 16
+ VT_DOCUMENTATION = 16,
+ VT_DECLARATION_FILE = 18
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ const ::flatbuffers::String *name() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_NAME);
}
- bool KeyCompareLessThan(const Object *o) const {
+ bool KeyCompareLessThan(const Object * const o) const {
return *name() < *o->name();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(name()->c_str(), val);
+ int KeyCompareWithValue(const char *_name) const {
+ return strcmp(name()->c_str(), _name);
}
- const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS);
+ 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;
@@ -766,40 +846,46 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
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<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);
}
- const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ /// File that this Object is declared in.
+ const ::flatbuffers::String *declaration_file() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ 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) &&
+ VerifyField<uint8_t>(verifier, VT_IS_STRUCT, 1) &&
+ VerifyField<int32_t>(verifier, VT_MINALIGN, 4) &&
+ VerifyField<int32_t>(verifier, VT_BYTESIZE, 4) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
verifier.VerifyVector(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.VerifyVector(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyOffset(verifier, VT_DECLARATION_FILE) &&
+ verifier.VerifyString(declaration_file()) &&
verifier.EndTable();
}
};
struct ObjectBuilder {
typedef Object Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ 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) {
@@ -811,35 +897,40 @@ struct ObjectBuilder {
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) {
+ 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) {
+ void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
}
- explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
+ fbb_.AddOffset(Object::VT_DECLARATION_FILE, declaration_file);
+ }
+ explicit ObjectBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Object> Finish() {
+ ::flatbuffers::Offset<Object> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Object>(end);
+ 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,
+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) {
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation = 0,
+ ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
ObjectBuilder builder_(_fbb);
+ builder_.add_declaration_file(declaration_file);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_bytesize(bytesize);
@@ -850,19 +941,21 @@ inline flatbuffers::Offset<Object> CreateObject(
return builder_.Finish();
}
-inline flatbuffers::Offset<Object> CreateObjectDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
+inline ::flatbuffers::Offset<Object> CreateObjectDirect(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
- std::vector<flatbuffers::Offset<reflection::Field>> *fields = 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) {
+ std::vector<::flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *documentation = nullptr,
+ const char *declaration_file = 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;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
+ auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
return reflection::CreateObject(
_fbb,
name__,
@@ -871,10 +964,11 @@ inline flatbuffers::Offset<Object> CreateObjectDirect(
minalign,
bytesize,
attributes__,
- documentation__);
+ documentation__,
+ declaration_file__);
}
-struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+struct RPCCall FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef RPCCallBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
@@ -883,14 +977,14 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_ATTRIBUTES = 10,
VT_DOCUMENTATION = 12
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ const ::flatbuffers::String *name() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_NAME);
}
- bool KeyCompareLessThan(const RPCCall *o) const {
+ bool KeyCompareLessThan(const RPCCall * const o) const {
return *name() < *o->name();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(name()->c_str(), val);
+ int KeyCompareWithValue(const char *_name) const {
+ return strcmp(name()->c_str(), _name);
}
const reflection::Object *request() const {
return GetPointer<const reflection::Object *>(VT_REQUEST);
@@ -898,13 +992,13 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
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<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);
+ 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 {
+ bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
@@ -924,30 +1018,30 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct RPCCallBuilder {
typedef RPCCall Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ void add_request(::flatbuffers::Offset<reflection::Object> request) {
fbb_.AddOffset(RPCCall::VT_REQUEST, request);
}
- void add_response(flatbuffers::Offset<reflection::Object> response) {
+ 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) {
+ 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) {
+ void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation);
}
- explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ explicit RPCCallBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<RPCCall> Finish() {
+ ::flatbuffers::Offset<RPCCall> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<RPCCall>(end);
+ auto o = ::flatbuffers::Offset<RPCCall>(end);
fbb_.Required(o, RPCCall::VT_NAME);
fbb_.Required(o, RPCCall::VT_REQUEST);
fbb_.Required(o, RPCCall::VT_RESPONSE);
@@ -955,13 +1049,13 @@ struct RPCCallBuilder {
}
};
-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) {
+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);
@@ -971,16 +1065,16 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCall(
return builder_.Finish();
}
-inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
+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) {
+ ::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;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
return reflection::CreateRPCCall(
_fbb,
name__,
@@ -990,33 +1084,38 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
documentation__);
}
-struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+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
+ VT_DOCUMENTATION = 10,
+ VT_DECLARATION_FILE = 12
};
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
+ const ::flatbuffers::String *name() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_NAME);
}
- bool KeyCompareLessThan(const Service *o) const {
+ bool KeyCompareLessThan(const Service * const o) const {
return *name() < *o->name();
}
- int KeyCompareWithValue(const char *val) const {
- return strcmp(name()->c_str(), val);
+ int KeyCompareWithValue(const char *_name) const {
+ return strcmp(name()->c_str(), _name);
+ }
+ 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::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<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);
}
- const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ /// File that this Service is declared in.
+ const ::flatbuffers::String *declaration_file() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_DECLARATION_FILE);
}
- bool Verify(flatbuffers::Verifier &verifier) const {
+ bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
@@ -1029,45 +1128,52 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.VerifyVector(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyOffset(verifier, VT_DECLARATION_FILE) &&
+ verifier.VerifyString(declaration_file()) &&
verifier.EndTable();
}
};
struct ServiceBuilder {
typedef Service Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ ::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) {
+ 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) {
+ 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) {
+ void add_documentation(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> documentation) {
fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation);
}
- explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ void add_declaration_file(::flatbuffers::Offset<::flatbuffers::String> declaration_file) {
+ fbb_.AddOffset(Service::VT_DECLARATION_FILE, declaration_file);
+ }
+ explicit ServiceBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Service> Finish() {
+ ::flatbuffers::Offset<Service> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Service>(end);
+ 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) {
+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,
+ ::flatbuffers::Offset<::flatbuffers::String> declaration_file = 0) {
ServiceBuilder builder_(_fbb);
+ builder_.add_declaration_file(declaration_file);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_calls(calls);
@@ -1075,25 +1181,106 @@ inline flatbuffers::Offset<Service> CreateService(
return builder_.Finish();
}
-inline flatbuffers::Offset<Service> CreateServiceDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
+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) {
+ 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,
+ const char *declaration_file = 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;
+ auto documentation__ = documentation ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*documentation) : 0;
+ auto declaration_file__ = declaration_file ? _fbb.CreateString(declaration_file) : 0;
return reflection::CreateService(
_fbb,
name__,
calls__,
attributes__,
- documentation__);
+ documentation__,
+ declaration_file__);
+}
+
+/// File specific information.
+/// Symbols declared within a file may be recovered by iterating over all
+/// symbols and examining the `declaration_file` field.
+struct SchemaFile FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
+ typedef SchemaFileBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_FILENAME = 4,
+ VT_INCLUDED_FILENAMES = 6
+ };
+ /// Filename, relative to project root.
+ const ::flatbuffers::String *filename() const {
+ return GetPointer<const ::flatbuffers::String *>(VT_FILENAME);
+ }
+ bool KeyCompareLessThan(const SchemaFile * const o) const {
+ return *filename() < *o->filename();
+ }
+ int KeyCompareWithValue(const char *_filename) const {
+ return strcmp(filename()->c_str(), _filename);
+ }
+ /// Names of included files, relative to project root.
+ const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *included_filenames() const {
+ return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *>(VT_INCLUDED_FILENAMES);
+ }
+ bool Verify(::flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_FILENAME) &&
+ verifier.VerifyString(filename()) &&
+ VerifyOffset(verifier, VT_INCLUDED_FILENAMES) &&
+ verifier.VerifyVector(included_filenames()) &&
+ verifier.VerifyVectorOfStrings(included_filenames()) &&
+ verifier.EndTable();
+ }
+};
+
+struct SchemaFileBuilder {
+ typedef SchemaFile Table;
+ ::flatbuffers::FlatBufferBuilder &fbb_;
+ ::flatbuffers::uoffset_t start_;
+ void add_filename(::flatbuffers::Offset<::flatbuffers::String> filename) {
+ fbb_.AddOffset(SchemaFile::VT_FILENAME, filename);
+ }
+ void add_included_filenames(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> included_filenames) {
+ fbb_.AddOffset(SchemaFile::VT_INCLUDED_FILENAMES, included_filenames);
+ }
+ explicit SchemaFileBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ ::flatbuffers::Offset<SchemaFile> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = ::flatbuffers::Offset<SchemaFile>(end);
+ fbb_.Required(o, SchemaFile::VT_FILENAME);
+ return o;
+ }
+};
+
+inline ::flatbuffers::Offset<SchemaFile> CreateSchemaFile(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
+ ::flatbuffers::Offset<::flatbuffers::String> filename = 0,
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> included_filenames = 0) {
+ SchemaFileBuilder builder_(_fbb);
+ builder_.add_included_filenames(included_filenames);
+ builder_.add_filename(filename);
+ return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<SchemaFile> CreateSchemaFileDirect(
+ ::flatbuffers::FlatBufferBuilder &_fbb,
+ const char *filename = nullptr,
+ const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *included_filenames = nullptr) {
+ auto filename__ = filename ? _fbb.CreateString(filename) : 0;
+ auto included_filenames__ = included_filenames ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*included_filenames) : 0;
+ return reflection::CreateSchemaFile(
+ _fbb,
+ filename__,
+ included_filenames__);
}
-struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+struct Schema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef SchemaBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_OBJECTS = 4,
@@ -1102,30 +1289,36 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FILE_EXT = 10,
VT_ROOT_TABLE = 12,
VT_SERVICES = 14,
- VT_ADVANCED_FEATURES = 16
+ VT_ADVANCED_FEATURES = 16,
+ VT_FBS_FILES = 18
};
- 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::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::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_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 ::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);
+ 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 {
+ /// All the files used in this compilation. Files are relative to where
+ /// flatc was invoked.
+ const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>> *fbs_files() const {
+ return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>> *>(VT_FBS_FILES);
+ }
+ bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
verifier.VerifyVector(objects()) &&
@@ -1142,60 +1335,68 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_SERVICES) &&
verifier.VerifyVector(services()) &&
verifier.VerifyVectorOfTables(services()) &&
- VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES) &&
+ VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES, 8) &&
+ VerifyOffset(verifier, VT_FBS_FILES) &&
+ verifier.VerifyVector(fbs_files()) &&
+ verifier.VerifyVectorOfTables(fbs_files()) &&
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) {
+ ::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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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)
+ void add_fbs_files(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>>> fbs_files) {
+ fbb_.AddOffset(Schema::VT_FBS_FILES, fbs_files);
+ }
+ explicit SchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
- flatbuffers::Offset<Schema> Finish() {
+ ::flatbuffers::Offset<Schema> Finish() {
const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Schema>(end);
+ 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)) {
+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),
+ ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<reflection::SchemaFile>>> fbs_files = 0) {
SchemaBuilder builder_(_fbb);
builder_.add_advanced_features(advanced_features);
+ builder_.add_fbs_files(fbs_files);
builder_.add_services(services);
builder_.add_root_table(root_table);
builder_.add_file_ext(file_ext);
@@ -1205,20 +1406,22 @@ inline flatbuffers::Offset<Schema> CreateSchema(
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,
+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)) {
+ ::flatbuffers::Offset<reflection::Object> root_table = 0,
+ std::vector<::flatbuffers::Offset<reflection::Service>> *services = nullptr,
+ reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0),
+ std::vector<::flatbuffers::Offset<reflection::SchemaFile>> *fbs_files = nullptr) {
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;
+ auto fbs_files__ = fbs_files ? _fbb.CreateVectorOfSortedTables<reflection::SchemaFile>(fbs_files) : 0;
return reflection::CreateSchema(
_fbb,
objects__,
@@ -1227,15 +1430,16 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
file_ext__,
root_table,
services__,
- advanced_features);
+ advanced_features,
+ fbs_files__);
}
inline const reflection::Schema *GetSchema(const void *buf) {
- return flatbuffers::GetRoot<reflection::Schema>(buf);
+ return ::flatbuffers::GetRoot<reflection::Schema>(buf);
}
inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
+ return ::flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
}
inline const char *SchemaIdentifier() {
@@ -1243,17 +1447,22 @@ inline const char *SchemaIdentifier() {
}
inline bool SchemaBufferHasIdentifier(const void *buf) {
- return flatbuffers::BufferHasIdentifier(
+ return ::flatbuffers::BufferHasIdentifier(
buf, SchemaIdentifier());
}
+inline bool SizePrefixedSchemaBufferHasIdentifier(const void *buf) {
+ return ::flatbuffers::BufferHasIdentifier(
+ buf, SchemaIdentifier(), true);
+}
+
inline bool VerifySchemaBuffer(
- flatbuffers::Verifier &verifier) {
+ ::flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
}
inline bool VerifySizePrefixedSchemaBuffer(
- flatbuffers::Verifier &verifier) {
+ ::flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
}
@@ -1262,14 +1471,14 @@ inline const char *SchemaExtension() {
}
inline void FinishSchemaBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<reflection::Schema> root) {
+ ::flatbuffers::FlatBufferBuilder &fbb,
+ ::flatbuffers::Offset<reflection::Schema> root) {
fbb.Finish(root, SchemaIdentifier());
}
inline void FinishSizePrefixedSchemaBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<reflection::Schema> root) {
+ ::flatbuffers::FlatBufferBuilder &fbb,
+ ::flatbuffers::Offset<reflection::Schema> root) {
fbb.FinishSizePrefixed(root, SchemaIdentifier());
}
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h b/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h
index e8e1e59487..c085952b60 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h
@@ -26,36 +26,36 @@
#include <memory>
#include <limits>
-#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
- #define FLATBUFFERS_CPP98_STL
-#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
-
-#if defined(FLATBUFFERS_CPP98_STL)
- #include <cctype>
-#endif // defined(FLATBUFFERS_CPP98_STL)
-
-// Detect C++17 compatible compiler.
-// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
-#if defined(FLATBUFFERS_USE_STD_OPTIONAL) \
- || (defined(__cplusplus) && __cplusplus >= 201703L) \
- || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
+#ifndef FLATBUFFERS_USE_STD_OPTIONAL
+ // Detect C++17 compatible compiler.
+ // __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
+ #if (defined(__cplusplus) && __cplusplus >= 201703L) \
+ || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+ #define FLATBUFFERS_USE_STD_OPTIONAL 1
+ #else
+ #define FLATBUFFERS_USE_STD_OPTIONAL 0
+ #endif // (defined(__cplusplus) && __cplusplus >= 201703L) ...
+#endif // FLATBUFFERS_USE_STD_OPTIONAL
+
+#if FLATBUFFERS_USE_STD_OPTIONAL
#include <optional>
- #ifndef FLATBUFFERS_USE_STD_OPTIONAL
- #define FLATBUFFERS_USE_STD_OPTIONAL
+#endif
+
+#ifndef FLATBUFFERS_USE_STD_SPAN
+ // Testing __cpp_lib_span requires including either <version> or <span>,
+ // both of which were added in C++20.
+ // See: https://en.cppreference.com/w/cpp/utility/feature_test
+ #if defined(__cplusplus) && __cplusplus >= 202002L
+ #define FLATBUFFERS_USE_STD_SPAN 1
#endif
-#endif // defined(FLATBUFFERS_USE_STD_OPTIONAL) ...
+#endif // FLATBUFFERS_USE_STD_SPAN
-// The __cpp_lib_span is the predefined feature macro.
#if defined(FLATBUFFERS_USE_STD_SPAN)
- #include <span>
-#elif defined(__cpp_lib_span) && defined(__has_include)
- #if __has_include(<span>)
- #include <span>
- #define FLATBUFFERS_USE_STD_SPAN
- #endif
+ #include <array>
+ #include <span>
#else
// Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined.
- #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) || defined(FLATBUFFERS_CPP98_STL)
+ #if !defined(FLATBUFFERS_TEMPLATES_ALIASES)
#define FLATBUFFERS_SPAN_MINIMAL
#else
// Enable implicit construction of a span<T,N> from a std::array<T,N>.
@@ -63,135 +63,32 @@
#endif
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
-// This header provides backwards compatibility for C++98 STLs like stlport.
+// This header provides backwards compatibility for older versions of the STL.
namespace flatbuffers {
-// Retrieve ::back() from a string in a way that is compatible with pre C++11
-// STLs (e.g stlport).
-inline char& string_back(std::string &value) {
- return value[value.length() - 1];
-}
-
-inline char string_back(const std::string &value) {
- return value[value.length() - 1];
-}
-
-// Helper method that retrieves ::data() from a vector in a way that is
-// compatible with pre C++11 STLs (e.g stlport).
-template <typename T> inline T *vector_data(std::vector<T> &vector) {
- // In some debug environments, operator[] does bounds checking, so &vector[0]
- // can't be used.
- return vector.empty() ? nullptr : &vector[0];
-}
-
-template <typename T> inline const T *vector_data(
- const std::vector<T> &vector) {
- return vector.empty() ? nullptr : &vector[0];
-}
-
-template <typename T, typename V>
-inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
- #if defined(FLATBUFFERS_CPP98_STL)
- vector->push_back(data);
- #else
- vector->emplace_back(std::forward<V>(data));
- #endif // defined(FLATBUFFERS_CPP98_STL)
-}
-
-#ifndef FLATBUFFERS_CPP98_STL
- #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
- template <typename T>
- using numeric_limits = std::numeric_limits<T>;
- #else
- template <typename T> class numeric_limits :
- public std::numeric_limits<T> {};
- #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
+#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
+ template <typename T>
+ using numeric_limits = std::numeric_limits<T>;
#else
template <typename T> class numeric_limits :
- public std::numeric_limits<T> {
- public:
- // Android NDK fix.
- static T lowest() {
- return std::numeric_limits<T>::min();
- }
- };
-
- template <> class numeric_limits<float> :
- public std::numeric_limits<float> {
- public:
- static float lowest() { return -FLT_MAX; }
- };
-
- template <> class numeric_limits<double> :
- public std::numeric_limits<double> {
- public:
- static double lowest() { return -DBL_MAX; }
- };
-
- template <> class numeric_limits<unsigned long long> {
- public:
- static unsigned long long min() { return 0ULL; }
- static unsigned long long max() { return ~0ULL; }
- static unsigned long long lowest() {
- return numeric_limits<unsigned long long>::min();
- }
- };
-
- template <> class numeric_limits<long long> {
- public:
- static long long min() {
- return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
- }
- static long long max() {
- return static_cast<long long>(
- (1ULL << ((sizeof(long long) << 3) - 1)) - 1);
- }
- static long long lowest() {
- return numeric_limits<long long>::min();
- }
- };
-#endif // FLATBUFFERS_CPP98_STL
+ public std::numeric_limits<T> {};
+#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
- #ifndef FLATBUFFERS_CPP98_STL
- template <typename T> using is_scalar = std::is_scalar<T>;
- template <typename T, typename U> using is_same = std::is_same<T,U>;
- template <typename T> using is_floating_point = std::is_floating_point<T>;
- template <typename T> using is_unsigned = std::is_unsigned<T>;
- template <typename T> using is_enum = std::is_enum<T>;
- template <typename T> using make_unsigned = std::make_unsigned<T>;
- template<bool B, class T, class F>
- using conditional = std::conditional<B, T, F>;
- template<class T, T v>
- using integral_constant = std::integral_constant<T, v>;
- template <bool B>
- using bool_constant = integral_constant<bool, B>;
- #else
- // Map C++ TR1 templates defined by stlport.
- template <typename T> using is_scalar = std::tr1::is_scalar<T>;
- template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
- template <typename T> using is_floating_point =
- std::tr1::is_floating_point<T>;
- template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
- template <typename T> using is_enum = std::tr1::is_enum<T>;
- // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
- template<typename T> struct make_unsigned {
- static_assert(is_unsigned<T>::value, "Specialization not implemented!");
- using type = T;
- };
- template<> struct make_unsigned<char> { using type = unsigned char; };
- template<> struct make_unsigned<short> { using type = unsigned short; };
- template<> struct make_unsigned<int> { using type = unsigned int; };
- template<> struct make_unsigned<long> { using type = unsigned long; };
- template<>
- struct make_unsigned<long long> { using type = unsigned long long; };
- template<bool B, class T, class F>
- using conditional = std::tr1::conditional<B, T, F>;
- template<class T, T v>
- using integral_constant = std::tr1::integral_constant<T, v>;
- template <bool B>
- using bool_constant = integral_constant<bool, B>;
- #endif // !FLATBUFFERS_CPP98_STL
+ template <typename T> using is_scalar = std::is_scalar<T>;
+ template <typename T, typename U> using is_same = std::is_same<T,U>;
+ template <typename T> using is_floating_point = std::is_floating_point<T>;
+ template <typename T> using is_unsigned = std::is_unsigned<T>;
+ template <typename T> using is_enum = std::is_enum<T>;
+ template <typename T> using make_unsigned = std::make_unsigned<T>;
+ template<bool B, class T, class F>
+ using conditional = std::conditional<B, T, F>;
+ template<class T, T v>
+ using integral_constant = std::integral_constant<T, v>;
+ template <bool B>
+ using bool_constant = integral_constant<bool, B>;
+ using true_type = std::true_type;
+ using false_type = std::false_type;
#else
// MSVC 2010 doesn't support C++11 aliases.
template <typename T> struct is_scalar : public std::is_scalar<T> {};
@@ -207,128 +104,39 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
struct integral_constant : public std::integral_constant<T, v> {};
template <bool B>
struct bool_constant : public integral_constant<bool, B> {};
+ typedef bool_constant<true> true_type;
+ typedef bool_constant<false> false_type;
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
-#ifndef FLATBUFFERS_CPP98_STL
- #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
- template <class T> using unique_ptr = std::unique_ptr<T>;
- #else
- // MSVC 2010 doesn't support C++11 aliases.
- // We're manually "aliasing" the class here as we want to bring unique_ptr
- // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
- // namespace we have a completely independent implementation (see below)
- // for C++98 STL implementations.
- template <class T> class unique_ptr : public std::unique_ptr<T> {
- public:
- unique_ptr() {}
- explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
- unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
- unique_ptr(unique_ptr&& u) { *this = std::move(u); }
- unique_ptr& operator=(std::unique_ptr<T>&& u) {
- std::unique_ptr<T>::reset(u.release());
- return *this;
- }
- unique_ptr& operator=(unique_ptr&& u) {
- std::unique_ptr<T>::reset(u.release());
- return *this;
- }
- unique_ptr& operator=(T* p) {
- return std::unique_ptr<T>::operator=(p);
- }
- };
- #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
+#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
+ template <class T> using unique_ptr = std::unique_ptr<T>;
#else
- // Very limited implementation of unique_ptr.
- // This is provided simply to allow the C++ code generated from the default
- // settings to function in C++98 environments with no modifications.
- template <class T> class unique_ptr {
- public:
- typedef T element_type;
-
- unique_ptr() : ptr_(nullptr) {}
- explicit unique_ptr(T* p) : ptr_(p) {}
- unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
- unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
- reset(const_cast<unique_ptr*>(&u)->release());
- }
- ~unique_ptr() { reset(); }
-
- unique_ptr& operator=(const unique_ptr& u) {
- reset(const_cast<unique_ptr*>(&u)->release());
+ // MSVC 2010 doesn't support C++11 aliases.
+ // We're manually "aliasing" the class here as we want to bring unique_ptr
+ // into the flatbuffers namespace. We have unique_ptr in the flatbuffers
+ // namespace we have a completely independent implementation (see below)
+ // for C++98 STL implementations.
+ template <class T> class unique_ptr : public std::unique_ptr<T> {
+ public:
+ unique_ptr() {}
+ explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
+ unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
+ unique_ptr(unique_ptr&& u) { *this = std::move(u); }
+ unique_ptr& operator=(std::unique_ptr<T>&& u) {
+ std::unique_ptr<T>::reset(u.release());
return *this;
}
-
unique_ptr& operator=(unique_ptr&& u) {
- reset(u.release());
+ std::unique_ptr<T>::reset(u.release());
return *this;
}
-
unique_ptr& operator=(T* p) {
- reset(p);
- return *this;
+ return std::unique_ptr<T>::operator=(p);
}
-
- const T& operator*() const { return *ptr_; }
- T* operator->() const { return ptr_; }
- T* get() const noexcept { return ptr_; }
- explicit operator bool() const { return ptr_ != nullptr; }
-
- // modifiers
- T* release() {
- T* value = ptr_;
- ptr_ = nullptr;
- return value;
- }
-
- void reset(T* p = nullptr) {
- T* value = ptr_;
- ptr_ = p;
- if (value) delete value;
- }
-
- void swap(unique_ptr& u) {
- T* temp_ptr = ptr_;
- ptr_ = u.ptr_;
- u.ptr_ = temp_ptr;
- }
-
- private:
- T* ptr_;
};
+#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
- template <class T> bool operator==(const unique_ptr<T>& x,
- const unique_ptr<T>& y) {
- return x.get() == y.get();
- }
-
- template <class T, class D> bool operator==(const unique_ptr<T>& x,
- const D* y) {
- return static_cast<D*>(x.get()) == y;
- }
-
- template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
- return reinterpret_cast<intptr_t>(x.get()) == y;
- }
-
- template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
- return !!x;
- }
-
- template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
- return !!x;
- }
-
- template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
- return !x;
- }
-
- template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
- return !x;
- }
-
-#endif // !FLATBUFFERS_CPP98_STL
-
-#ifdef FLATBUFFERS_USE_STD_OPTIONAL
+#if FLATBUFFERS_USE_STD_OPTIONAL
template<class T>
using Optional = std::optional<T>;
using nullopt_t = std::nullopt_t;
@@ -484,17 +292,43 @@ FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
namespace internal {
// This is SFINAE helper class for checking of a common condition:
// > This overload only participates in overload resolution
- // > Check whether a pointer to an array of U can be converted
- // > to a pointer to an array of E.
- // This helper is used for checking of 'U -> const U'.
- template<class E, std::size_t Extent, class U, std::size_t N>
- struct is_span_convertable {
+ // > Check whether a pointer to an array of From can be converted
+ // > to a pointer to an array of To.
+ // This helper is used for checking of 'From -> const From'.
+ template<class To, std::size_t Extent, class From, std::size_t N>
+ struct is_span_convertible {
using type =
- typename std::conditional<std::is_convertible<U (*)[], E (*)[]>::value
+ typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value
&& (Extent == dynamic_extent || N == Extent),
int, void>::type;
};
+ template<typename T>
+ struct SpanIterator {
+ // TODO: upgrade to std::random_access_iterator_tag.
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+ using value_type = typename std::remove_cv<T>::type;
+ using reference = T&;
+ using pointer = T*;
+
+ // Convince MSVC compiler that this iterator is trusted (it is verified).
+ #ifdef _MSC_VER
+ using _Unchecked_type = pointer;
+ #endif // _MSC_VER
+
+ SpanIterator(pointer ptr) : ptr_(ptr) {}
+ reference operator*() const { return *ptr_; }
+ pointer operator->() { return ptr_; }
+ SpanIterator& operator++() { ptr_++; return *this; }
+ SpanIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
+
+ friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; }
+ friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; }
+
+ private:
+ pointer ptr_;
+ };
} // namespace internal
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
@@ -534,6 +368,13 @@ class span FLATBUFFERS_FINAL_CLASS {
return data_;
}
+ #if !defined(FLATBUFFERS_SPAN_MINIMAL)
+ using Iterator = internal::SpanIterator<T>;
+
+ Iterator begin() const { return Iterator(data()); }
+ Iterator end() const { return Iterator(data() + size()); }
+ #endif
+
// Returns a reference to the idx-th element of the sequence.
// The behavior is undefined if the idx is greater than or equal to size().
FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const {
@@ -577,7 +418,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// extent == 0 || extent == flatbuffers::dynamic_extent.
// A dummy template argument N is need dependency for SFINAE.
template<std::size_t N = 0,
- typename internal::is_span_convertable<element_type, Extent, element_type, (N - N)>::type = 0>
+ typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
count_(0) {
static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
@@ -590,12 +431,12 @@ class span FLATBUFFERS_FINAL_CLASS {
// std::remove_pointer_t<decltype(std::data(arr))>(*)[]
// is convertible to element_type (*)[].
template<std::size_t N,
- typename internal::is_span_convertable<element_type, Extent, element_type, N>::type = 0>
+ typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
: data_(arr), count_(N) {}
template<class U, std::size_t N,
- typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
: data_(arr.data()), count_(N) {}
@@ -605,7 +446,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// : data_(arr.data()), count_(N) {}
template<class U, std::size_t N,
- typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
: data_(arr.data()), count_(N) {}
@@ -615,7 +456,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// if extent == std::dynamic_extent || N == extent is true and U (*)[]
// is convertible to element_type (*)[].
template<class U, std::size_t N,
- typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
+ typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
: span(s.data(), s.size()) {
}
@@ -625,48 +466,47 @@ class span FLATBUFFERS_FINAL_CLASS {
private:
// This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
pointer const data_;
- const size_type count_;
+ size_type count_;
};
+#endif // defined(FLATBUFFERS_USE_STD_SPAN)
- #if !defined(FLATBUFFERS_SPAN_MINIMAL)
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
- return span<U, N>(arr);
- }
-
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
- return span<const U, N>(arr);
- }
+#if !defined(FLATBUFFERS_SPAN_MINIMAL)
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
+ return span<ElementType, Extent>(arr);
+}
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
- return span<U, N>(arr);
- }
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
+ return span<const ElementType, Extent>(arr);
+}
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
- return span<const U, N>(arr);
- }
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
+ return span<ElementType, Extent>(arr);
+}
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
- return span<U, dynamic_extent>(first, count);
- }
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
+ return span<const ElementType, Extent>(arr);
+}
- template<class U, std::size_t N>
- FLATBUFFERS_CONSTEXPR_CPP11
- flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
- return span<const U, dynamic_extent>(first, count);
- }
-#endif
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
+ return span<ElementType, dynamic_extent>(first, count);
+}
-#endif // defined(FLATBUFFERS_USE_STD_SPAN)
+template<class ElementType, std::size_t Extent>
+FLATBUFFERS_CONSTEXPR_CPP11
+flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
+ return span<const ElementType, dynamic_extent>(first, count);
+}
+#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/string.h b/contrib/libs/flatbuffers/include/flatbuffers/string.h
new file mode 100644
index 0000000000..e6b98f0c9f
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/string.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 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_STRING_H_
+#define FLATBUFFERS_STRING_H_
+
+#include "base.h"
+#include "vector.h"
+
+namespace flatbuffers {
+
+struct String : public Vector<char> {
+ const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
+ std::string str() const { return std::string(c_str(), size()); }
+
+ // clang-format off
+ #ifdef FLATBUFFERS_HAS_STRING_VIEW
+ flatbuffers::string_view string_view() const {
+ return flatbuffers::string_view(c_str(), size());
+ }
+ #endif // FLATBUFFERS_HAS_STRING_VIEW
+ // clang-format on
+
+ bool operator<(const String &o) const {
+ return StringLessThan(this->data(), this->size(), o.data(), o.size());
+ }
+};
+
+// Convenience function to get std::string from a String returning an empty
+// string on null pointer.
+static inline std::string GetString(const String *str) {
+ return str ? str->str() : "";
+}
+
+// Convenience function to get char* from a String returning an empty string on
+// null pointer.
+static inline const char *GetCstring(const String *str) {
+ return str ? str->c_str() : "";
+}
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+// Convenience function to get string_view from a String returning an empty
+// string_view on null pointer.
+static inline flatbuffers::string_view GetStringView(const String *str) {
+ return str ? str->string_view() : flatbuffers::string_view();
+}
+#endif // FLATBUFFERS_HAS_STRING_VIEW
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_STRING_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/struct.h b/contrib/libs/flatbuffers/include/flatbuffers/struct.h
new file mode 100644
index 0000000000..3faf183a6a
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/struct.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 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_STRUCT_H_
+#define FLATBUFFERS_STRUCT_H_
+
+#include "base.h"
+
+namespace flatbuffers {
+
+// "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.
+
+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 reinterpret_cast<T>(&data_[o]);
+ }
+
+ const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
+ uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
+
+ private:
+ // private constructor & copy constructor: you obtain instances of this
+ // class by pointing to existing data only
+ Struct();
+ Struct(const Struct &);
+ Struct &operator=(const Struct &);
+
+ uint8_t data_[1];
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_STRUCT_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/table.h b/contrib/libs/flatbuffers/include/flatbuffers/table.h
new file mode 100644
index 0000000000..9ceafaa143
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/table.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2021 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_TABLE_H_
+#define FLATBUFFERS_TABLE_H_
+
+#include "base.h"
+#include "verifier.h"
+
+namespace flatbuffers {
+
+// "tables" use an offset table (possibly shared) that allows fields to be
+// omitted and added at will, but uses an extra indirection to read.
+class Table {
+ public:
+ const uint8_t *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, typename OffsetSize = uoffset_t>
+ P GetPointer(voffset_t field) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? reinterpret_cast<P>(p + ReadScalar<OffsetSize>(p))
+ : nullptr;
+ }
+ template<typename P, typename OffsetSize = uoffset_t>
+ P GetPointer(voffset_t field) const {
+ return const_cast<Table *>(this)->GetPointer<P, OffsetSize>(field);
+ }
+
+ template<typename P> P GetPointer64(voffset_t field) {
+ return GetPointer<P, uoffset64_t>(field);
+ }
+
+ template<typename P> P GetPointer64(voffset_t field) const {
+ return GetPointer<P, uoffset64_t>(field);
+ }
+
+ template<typename P> P GetStruct(voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = const_cast<uint8_t *>(data_ + field_offset);
+ return field_offset ? reinterpret_cast<P>(p) : nullptr;
+ }
+
+ template<typename Raw, typename Face>
+ flatbuffers::Optional<Face> GetOptional(voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p)))
+ : Optional<Face>();
+ }
+
+ template<typename T> bool SetField(voffset_t field, T val, T def) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset) return IsTheSameAs(val, def);
+ WriteScalar(data_ + field_offset, val);
+ return true;
+ }
+ template<typename T> bool SetField(voffset_t field, T val) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset) return false;
+ WriteScalar(data_ + field_offset, val);
+ return true;
+ }
+
+ bool SetPointer(voffset_t field, const uint8_t *val) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ if (!field_offset) return false;
+ WriteScalar(data_ + field_offset,
+ static_cast<uoffset_t>(val - (data_ + field_offset)));
+ return true;
+ }
+
+ uint8_t *GetAddressOf(voffset_t field) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return field_offset ? data_ + field_offset : nullptr;
+ }
+ const uint8_t *GetAddressOf(voffset_t field) const {
+ return const_cast<Table *>(this)->GetAddressOf(field);
+ }
+
+ 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 &verifier) const {
+ return verifier.VerifyTableStart(data_);
+ }
+
+ // Verify a particular field.
+ template<typename T>
+ bool VerifyField(const Verifier &verifier, voffset_t field,
+ size_t align) const {
+ // Calling GetOptionalFieldOffset should be safe now thanks to
+ // VerifyTable().
+ auto field_offset = GetOptionalFieldOffset(field);
+ // Check the actual field.
+ return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
+ }
+
+ // VerifyField for required fields.
+ template<typename T>
+ bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
+ size_t align) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) &&
+ verifier.VerifyField<T>(data_, field_offset, align);
+ }
+
+ // Versions for offsets.
+ template<typename OffsetT = uoffset_t>
+ bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return !field_offset || verifier.VerifyOffset<OffsetT>(data_, field_offset);
+ }
+
+ template<typename OffsetT = uoffset_t>
+ bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) &&
+ verifier.VerifyOffset<OffsetT>(data_, field_offset);
+ }
+
+ bool VerifyOffset64(const Verifier &verifier, voffset_t field) const {
+ return VerifyOffset<uoffset64_t>(verifier, field);
+ }
+
+ bool VerifyOffset64Required(const Verifier &verifier, voffset_t field) const {
+ return VerifyOffsetRequired<uoffset64_t>(verifier, field);
+ }
+
+ private:
+ // private constructor & copy constructor: you obtain instances of this
+ // class by pointing to existing data only
+ Table();
+ Table(const Table &other);
+ Table &operator=(const Table &);
+
+ uint8_t data_[1];
+};
+
+// This specialization allows avoiding warnings like:
+// MSVC C4800: type: forcing value to bool 'true' or 'false'.
+template<>
+inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
+ voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
+ : Optional<bool>();
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_TABLE_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/util.h b/contrib/libs/flatbuffers/include/flatbuffers/util.h
index 4493c561c2..03f61834c0 100644
--- a/contrib/libs/flatbuffers/include/flatbuffers/util.h
+++ b/contrib/libs/flatbuffers/include/flatbuffers/util.h
@@ -17,19 +17,22 @@
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
+#include <ctype.h>
#include <errno.h>
#include "base.h"
#include "stl_emulation.h"
#ifndef FLATBUFFERS_PREFER_PRINTF
+# include <iomanip>
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>
#endif // FLATBUFFERS_PREFER_PRINTF
-#include <iomanip>
+#include <cmath>
+#include <limits>
#include <string>
namespace flatbuffers {
@@ -94,7 +97,7 @@ template<typename T> size_t IntToDigitCount(T t) {
// 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();
+ T eps = std::numeric_limits<T>::epsilon();
while (t <= (-1 + eps) || (1 - eps) <= t) {
t /= 10;
digit_count++;
@@ -145,20 +148,6 @@ template<> inline std::string NumToString<unsigned char>(unsigned char 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) {
@@ -268,7 +257,7 @@ inline void strtoval_impl(double *val, const char *str, char **endptr) {
}
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
-__supress_ubsan__("float-cast-overflow")
+__suppress_ubsan__("float-cast-overflow")
inline void strtoval_impl(float *val, const char *str, char **endptr) {
*val = __strtof_impl(str, endptr);
}
@@ -325,6 +314,7 @@ inline bool StringToFloatImpl(T *val, const char *const str) {
strtoval_impl(val, str, const_cast<char **>(&end));
auto done = (end != str) && (*end == '\0');
if (!done) *val = 0; // erase partial result
+ if (done && std::isnan(*val)) { *val = std::numeric_limits<T>::quiet_NaN(); }
return done;
}
@@ -405,6 +395,18 @@ inline uint64_t StringToUInt(const char *s, int base = 10) {
return StringToIntegerImpl(&val, s, base) ? val : 0;
}
+inline bool StringIsFlatbufferNan(const std::string &s) {
+ return s == "nan" || s == "+nan" || s == "-nan";
+}
+
+inline bool StringIsFlatbufferPositiveInfinity(const std::string &s) {
+ return s == "inf" || s == "+inf" || s == "infinity" || s == "+infinity";
+}
+
+inline bool StringIsFlatbufferNegativeInfinity(const std::string &s) {
+ return s == "-inf" || s == "-infinity";
+}
+
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
std::string *dest);
typedef bool (*FileExistsFunction)(const char *filename);
@@ -461,6 +463,9 @@ std::string StripPath(const std::string &filepath);
// Strip the last component of the path + separator.
std::string StripFileName(const std::string &filepath);
+std::string StripPrefix(const std::string &filepath,
+ const std::string &prefix_to_remove);
+
// Concatenates a path with a filename, regardless of whether the path
// ends in a separator or not.
std::string ConCatPathFileName(const std::string &path,
@@ -468,6 +473,7 @@ std::string ConCatPathFileName(const std::string &path,
// Replaces any '\\' separators with '/'
std::string PosixPath(const char *path);
+std::string PosixPath(const std::string &path);
// This function ensure a directory exists, by recursively
// creating dirs for any parts of the path that don't exist yet.
@@ -477,6 +483,10 @@ void EnsureDirExists(const std::string &filepath);
// Returns the input path if the absolute path couldn't be resolved.
std::string AbsolutePath(const std::string &filepath);
+// Returns files relative to the --project_root path, prefixed with `//`.
+std::string RelativeToRootPath(const std::string &project,
+ 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
@@ -690,8 +700,32 @@ bool SetGlobalTestLocale(const char *locale_name,
bool ReadEnvironmentVariable(const char *var_name,
std::string *_value = nullptr);
-// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
-void SetupDefaultCRTReportMode();
+enum class Case {
+ kUnknown = 0,
+ // TheQuickBrownFox
+ kUpperCamel = 1,
+ // theQuickBrownFox
+ kLowerCamel = 2,
+ // the_quick_brown_fox
+ kSnake = 3,
+ // THE_QUICK_BROWN_FOX
+ kScreamingSnake = 4,
+ // THEQUICKBROWNFOX
+ kAllUpper = 5,
+ // thequickbrownfox
+ kAllLower = 6,
+ // the-quick-brown-fox
+ kDasher = 7,
+ // THEQuiCKBr_ownFox (or whatever you want, we won't change it)
+ kKeep = 8,
+ // the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123)
+ kSnake2 = 9,
+};
+
+// Convert the `input` string of case `input_case` to the specified
+// `output_case`.
+std::string ConvertCase(const std::string &input, Case output_case,
+ Case input_case = Case::kSnake);
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/vector.h b/contrib/libs/flatbuffers/include/flatbuffers/vector.h
new file mode 100644
index 0000000000..848e6c0b25
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/vector.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2021 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_VECTOR_H_
+#define FLATBUFFERS_VECTOR_H_
+
+#include "base.h"
+#include "buffer.h"
+#include "stl_emulation.h"
+
+namespace flatbuffers {
+
+struct String;
+
+// An STL compatible iterator implementation for Vector below, effectively
+// calling Get() for every element.
+template<typename T, typename IT, typename Data = uint8_t *,
+ typename SizeT = uoffset_t>
+struct VectorIterator {
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef IT value_type;
+ typedef ptrdiff_t difference_type;
+ typedef IT *pointer;
+ typedef IT &reference;
+
+ static const SizeT element_stride = IndirectHelper<T>::element_stride;
+
+ VectorIterator(Data data, SizeT i) : data_(data + element_stride * i) {}
+ VectorIterator(const VectorIterator &other) : data_(other.data_) {}
+ VectorIterator() : data_(nullptr) {}
+
+ 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_;
+ }
+
+ bool operator!=(const VectorIterator &other) const {
+ return data_ != other.data_;
+ }
+
+ difference_type operator-(const VectorIterator &other) const {
+ return (data_ - other.data_) / element_stride;
+ }
+
+ // Note: return type is incompatible with the standard
+ // `reference operator*()`.
+ IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
+
+ // Note: return type is incompatible with the standard
+ // `pointer operator->()`.
+ IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
+
+ VectorIterator &operator++() {
+ data_ += element_stride;
+ return *this;
+ }
+
+ VectorIterator operator++(int) {
+ VectorIterator temp(data_, 0);
+ data_ += element_stride;
+ return temp;
+ }
+
+ VectorIterator operator+(const SizeT &offset) const {
+ return VectorIterator(data_ + offset * element_stride, 0);
+ }
+
+ VectorIterator &operator+=(const SizeT &offset) {
+ data_ += offset * element_stride;
+ return *this;
+ }
+
+ VectorIterator &operator--() {
+ data_ -= element_stride;
+ return *this;
+ }
+
+ VectorIterator operator--(int) {
+ VectorIterator temp(data_, 0);
+ data_ -= element_stride;
+ return temp;
+ }
+
+ VectorIterator operator-(const SizeT &offset) const {
+ return VectorIterator(data_ - offset * element_stride, 0);
+ }
+
+ VectorIterator &operator-=(const SizeT &offset) {
+ data_ -= offset * element_stride;
+ return *this;
+ }
+
+ private:
+ Data data_;
+};
+
+template<typename T, typename IT, typename SizeT = uoffset_t>
+using VectorConstIterator = VectorIterator<T, IT, const uint8_t *, SizeT>;
+
+template<typename Iterator>
+struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
+ explicit VectorReverseIterator(Iterator iter)
+ : std::reverse_iterator<Iterator>(iter) {}
+
+ // Note: return type is incompatible with the standard
+ // `reference operator*()`.
+ typename Iterator::value_type operator*() const {
+ auto tmp = std::reverse_iterator<Iterator>::current;
+ return *--tmp;
+ }
+
+ // Note: return type is incompatible with the standard
+ // `pointer operator->()`.
+ typename Iterator::value_type operator->() const {
+ auto tmp = std::reverse_iterator<Iterator>::current;
+ return *--tmp;
+ }
+};
+
+// 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 SizeT = uoffset_t> class Vector {
+ public:
+ typedef VectorIterator<T,
+ typename IndirectHelper<T>::mutable_return_type,
+ uint8_t *, SizeT>
+ iterator;
+ typedef VectorConstIterator<T, typename IndirectHelper<T>::return_type,
+ SizeT>
+ const_iterator;
+ typedef VectorReverseIterator<iterator> reverse_iterator;
+ typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
+
+ typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
+ scalar_tag;
+
+ static FLATBUFFERS_CONSTEXPR bool is_span_observable =
+ scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN || sizeof(T) == 1);
+
+ SizeT size() const { return EndianScalar(length_); }
+
+ // Deprecated: use size(). Here for backwards compatibility.
+ FLATBUFFERS_ATTRIBUTE([[deprecated("use size() instead")]])
+ SizeT Length() const { return size(); }
+
+ typedef SizeT size_type;
+ typedef typename IndirectHelper<T>::return_type return_type;
+ typedef typename IndirectHelper<T>::mutable_return_type
+ mutable_return_type;
+ typedef return_type value_type;
+
+ return_type Get(SizeT i) const {
+ FLATBUFFERS_ASSERT(i < size());
+ return IndirectHelper<T>::Read(Data(), i);
+ }
+
+ return_type operator[](SizeT 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(SizeT i) const {
+ return static_cast<E>(Get(i));
+ }
+
+ // If this a vector of unions, this does the cast for you. There's no check
+ // to make sure this is the right type!
+ template<typename U> const U *GetAs(SizeT i) const {
+ return reinterpret_cast<const U *>(Get(i));
+ }
+
+ // If this a vector of unions, this does the cast for you. There's no check
+ // to make sure this is actually a string!
+ const String *GetAsString(SizeT i) const {
+ return reinterpret_cast<const String *>(Get(i));
+ }
+
+ const void *GetStructFromOffset(size_t o) const {
+ return reinterpret_cast<const void *>(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()); }
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
+ const_iterator cbegin() const { return begin(); }
+
+ const_iterator cend() const { return end(); }
+
+ const_reverse_iterator crbegin() const { return rbegin(); }
+
+ const_reverse_iterator crend() const { return rend(); }
+
+ // Change elements if you have a non-const pointer to this object.
+ // Scalars only. See reflection.h, and the documentation.
+ void Mutate(SizeT i, const T &val) {
+ FLATBUFFERS_ASSERT(i < size());
+ WriteScalar(data() + i, val);
+ }
+
+ // Change an element of a vector of tables (or strings).
+ // "val" points to the new table/string, as you can obtain from
+ // e.g. reflection::AddFlatBuffer().
+ void MutateOffset(SizeT i, const uint8_t *val) {
+ FLATBUFFERS_ASSERT(i < size());
+ static_assert(sizeof(T) == sizeof(SizeT), "Unrelated types");
+ WriteScalar(data() + i,
+ static_cast<SizeT>(val - (Data() + i * sizeof(SizeT))));
+ }
+
+ // Get a mutable pointer to tables/strings inside this vector.
+ mutable_return_type GetMutableObject(SizeT i) const {
+ FLATBUFFERS_ASSERT(i < size());
+ return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
+ }
+
+ // The raw data in little endian format. Use with care.
+ const uint8_t *Data() const {
+ return reinterpret_cast<const uint8_t *>(&length_ + 1);
+ }
+
+ uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+ // Similarly, but typed, much like std::vector::data
+ const T *data() const { return reinterpret_cast<const T *>(Data()); }
+ T *data() { return reinterpret_cast<T *>(Data()); }
+
+ template<typename K> return_type LookupByKey(K key) const {
+ void *search_result = std::bsearch(
+ &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
+
+ if (!search_result) {
+ return nullptr; // Key not found.
+ }
+
+ const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
+
+ return IndirectHelper<T>::Read(element, 0);
+ }
+
+ template<typename K> mutable_return_type MutableLookupByKey(K key) {
+ return const_cast<mutable_return_type>(LookupByKey(key));
+ }
+
+ protected:
+ // This class is only used to access pre-existing data. Don't ever
+ // try to construct these manually.
+ Vector();
+
+ SizeT length_;
+
+ private:
+ // This class is a pointer. Copying will therefore create an invalid object.
+ // Private and unimplemented copy constructor.
+ Vector(const Vector &);
+ Vector &operator=(const Vector &);
+
+ template<typename K> static int KeyCompare(const void *ap, const void *bp) {
+ const K *key = reinterpret_cast<const K *>(ap);
+ const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
+ auto table = IndirectHelper<T>::Read(data, 0);
+
+ // std::bsearch compares with the operands transposed, so we negate the
+ // result here.
+ return -table->KeyCompareWithValue(*key);
+ }
+};
+
+template<typename T> using Vector64 = Vector<T, uoffset64_t>;
+
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> &vec)
+ FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::is_span_observable,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return span<U>(vec.data(), vec.size());
+}
+
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
+ const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::is_span_observable,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return span<const U>(vec.data(), vec.size());
+}
+
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
+ Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::scalar_tag::value,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return span<uint8_t>(vec.Data(), vec.size() * sizeof(U));
+}
+
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
+ const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::scalar_tag::value,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
+}
+
+// Convenient helper functions to get a span of any vector, regardless
+// of whether it is null or not (the field is not set).
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr)
+ FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::is_span_observable,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return ptr ? make_span(*ptr) : span<U>();
+}
+
+template<class U>
+FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
+ const Vector<U> *ptr) FLATBUFFERS_NOEXCEPT {
+ static_assert(Vector<U>::is_span_observable,
+ "wrong type U, only LE-scalar, or byte types are allowed");
+ return ptr ? make_span(*ptr) : span<const U>();
+}
+
+// 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).
+class VectorOfAny {
+ public:
+ uoffset_t size() const { return EndianScalar(length_); }
+
+ const uint8_t *Data() const {
+ return reinterpret_cast<const uint8_t *>(&length_ + 1);
+ }
+ uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
+
+ protected:
+ VectorOfAny();
+
+ uoffset_t length_;
+
+ private:
+ VectorOfAny(const VectorOfAny &);
+ VectorOfAny &operator=(const VectorOfAny &);
+};
+
+template<typename T, typename U>
+Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
+ static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+ return reinterpret_cast<Vector<Offset<T>> *>(ptr);
+}
+
+template<typename T, typename U>
+const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
+ static_assert(std::is_base_of<T, U>::value, "Unrelated types");
+ return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
+}
+
+// Convenient helper function to get the length of any vector, regardless
+// of whether it is null or not (the field is not set).
+template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
+ return v ? v->size() : 0;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_VERIFIER_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/vector_downward.h b/contrib/libs/flatbuffers/include/flatbuffers/vector_downward.h
new file mode 100644
index 0000000000..7fd2551cfc
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/vector_downward.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2021 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_VECTOR_DOWNWARD_H_
+#define FLATBUFFERS_VECTOR_DOWNWARD_H_
+
+#include <cstdint>
+
+#include <algorithm>
+
+#include "base.h"
+#include "default_allocator.h"
+#include "detached_buffer.h"
+
+namespace flatbuffers {
+
+// This is a minimal replication of std::vector<uint8_t> functionality,
+// except growing from higher to lower addresses. i.e. push_back() inserts data
+// in the lowest address in the vector.
+// Since this vector leaves the lower part unused, we support a "scratch-pad"
+// that can be stored there for temporary data, to share the allocated space.
+// Essentially, this supports 2 std::vectors in a single buffer.
+template<typename SizeT = uoffset_t> class vector_downward {
+ public:
+ explicit vector_downward(size_t initial_size, Allocator *allocator,
+ bool own_allocator, size_t buffer_minalign,
+ const SizeT max_size = FLATBUFFERS_MAX_BUFFER_SIZE)
+ : allocator_(allocator),
+ own_allocator_(own_allocator),
+ initial_size_(initial_size),
+ max_size_(max_size),
+ buffer_minalign_(buffer_minalign),
+ reserved_(0),
+ size_(0),
+ buf_(nullptr),
+ cur_(nullptr),
+ scratch_(nullptr) {}
+
+ vector_downward(vector_downward &&other) noexcept
+ // clang-format on
+ : allocator_(other.allocator_),
+ own_allocator_(other.own_allocator_),
+ initial_size_(other.initial_size_),
+ max_size_(other.max_size_),
+ buffer_minalign_(other.buffer_minalign_),
+ reserved_(other.reserved_),
+ size_(other.size_),
+ buf_(other.buf_),
+ cur_(other.cur_),
+ scratch_(other.scratch_) {
+ // No change in other.allocator_
+ // No change in other.initial_size_
+ // No change in other.buffer_minalign_
+ other.own_allocator_ = false;
+ other.reserved_ = 0;
+ other.buf_ = nullptr;
+ other.cur_ = nullptr;
+ other.scratch_ = nullptr;
+ }
+
+ vector_downward &operator=(vector_downward &&other) noexcept {
+ // Move construct a temporary and swap idiom
+ vector_downward temp(std::move(other));
+ swap(temp);
+ return *this;
+ }
+
+ ~vector_downward() {
+ clear_buffer();
+ clear_allocator();
+ }
+
+ void reset() {
+ clear_buffer();
+ clear();
+ }
+
+ void clear() {
+ if (buf_) {
+ cur_ = buf_ + reserved_;
+ } else {
+ reserved_ = 0;
+ cur_ = nullptr;
+ }
+ size_ = 0;
+ clear_scratch();
+ }
+
+ void clear_scratch() { scratch_ = buf_; }
+
+ void clear_allocator() {
+ if (own_allocator_ && allocator_) { delete allocator_; }
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ }
+
+ void clear_buffer() {
+ if (buf_) Deallocate(allocator_, buf_, reserved_);
+ buf_ = nullptr;
+ }
+
+ // Relinquish the pointer to the caller.
+ uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
+ auto *buf = buf_;
+ allocated_bytes = reserved_;
+ offset = vector_downward::offset();
+
+ // release_raw only relinquishes the buffer ownership.
+ // Does not deallocate or reset the allocator. Destructor will do that.
+ buf_ = nullptr;
+ clear();
+ return buf;
+ }
+
+ // Relinquish the pointer to the caller.
+ DetachedBuffer release() {
+ // allocator ownership (if any) is transferred to DetachedBuffer.
+ DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
+ size());
+ if (own_allocator_) {
+ allocator_ = nullptr;
+ own_allocator_ = false;
+ }
+ buf_ = nullptr;
+ clear();
+ return fb;
+ }
+
+ size_t ensure_space(size_t len) {
+ FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
+ // If the length is larger than the unused part of the buffer, we need to
+ // grow.
+ if (len > unused_buffer_size()) { reallocate(len); }
+ FLATBUFFERS_ASSERT(size() < max_size_);
+ return len;
+ }
+
+ inline uint8_t *make_space(size_t len) {
+ if (len) {
+ ensure_space(len);
+ cur_ -= len;
+ size_ += static_cast<SizeT>(len);
+ }
+ return cur_;
+ }
+
+ // Returns nullptr if using the DefaultAllocator.
+ Allocator *get_custom_allocator() { return allocator_; }
+
+ // The current offset into the buffer.
+ size_t offset() const { return cur_ - buf_; }
+
+ // The total size of the vector (both the buffer and scratch parts).
+ inline SizeT size() const { return size_; }
+
+ // The size of the buffer part of the vector that is currently unused.
+ SizeT unused_buffer_size() const { return static_cast<SizeT>(cur_ - scratch_); }
+
+ // The size of the scratch part of the vector.
+ SizeT scratch_size() const { return static_cast<SizeT>(scratch_ - buf_); }
+
+ size_t capacity() const { return reserved_; }
+
+ uint8_t *data() const {
+ FLATBUFFERS_ASSERT(cur_);
+ return cur_;
+ }
+
+ uint8_t *scratch_data() const {
+ FLATBUFFERS_ASSERT(buf_);
+ return buf_;
+ }
+
+ uint8_t *scratch_end() const {
+ FLATBUFFERS_ASSERT(scratch_);
+ return scratch_;
+ }
+
+ uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
+
+ void push(const uint8_t *bytes, size_t num) {
+ if (num > 0) { memcpy(make_space(num), bytes, num); }
+ }
+
+ // Specialized version of push() that avoids memcpy call for small data.
+ template<typename T> void push_small(const T &little_endian_t) {
+ make_space(sizeof(T));
+ *reinterpret_cast<T *>(cur_) = little_endian_t;
+ }
+
+ template<typename T> void scratch_push_small(const T &t) {
+ ensure_space(sizeof(T));
+ *reinterpret_cast<T *>(scratch_) = t;
+ scratch_ += sizeof(T);
+ }
+
+ // fill() is most frequently called with small byte counts (<= 4),
+ // which is why we're using loops rather than calling memset.
+ void fill(size_t zero_pad_bytes) {
+ make_space(zero_pad_bytes);
+ for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
+ }
+
+ // Version for when we know the size is larger.
+ // Precondition: zero_pad_bytes > 0
+ void fill_big(size_t zero_pad_bytes) {
+ memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
+ }
+
+ void pop(size_t bytes_to_remove) {
+ cur_ += bytes_to_remove;
+ size_ -= static_cast<SizeT>(bytes_to_remove);
+ }
+
+ void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
+
+ void swap(vector_downward &other) {
+ using std::swap;
+ swap(allocator_, other.allocator_);
+ swap(own_allocator_, other.own_allocator_);
+ swap(initial_size_, other.initial_size_);
+ swap(buffer_minalign_, other.buffer_minalign_);
+ swap(reserved_, other.reserved_);
+ swap(size_, other.size_);
+ swap(max_size_, other.max_size_);
+ swap(buf_, other.buf_);
+ swap(cur_, other.cur_);
+ swap(scratch_, other.scratch_);
+ }
+
+ void swap_allocator(vector_downward &other) {
+ using std::swap;
+ swap(allocator_, other.allocator_);
+ swap(own_allocator_, other.own_allocator_);
+ }
+
+ private:
+ // You shouldn't really be copying instances of this class.
+ FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &));
+ FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &));
+
+ Allocator *allocator_;
+ bool own_allocator_;
+ size_t initial_size_;
+
+ // The maximum size the vector can be.
+ SizeT max_size_;
+ size_t buffer_minalign_;
+ size_t reserved_;
+ SizeT size_;
+ uint8_t *buf_;
+ uint8_t *cur_; // Points at location between empty (below) and used (above).
+ uint8_t *scratch_; // Points to the end of the scratchpad in use.
+
+ void reallocate(size_t len) {
+ auto old_reserved = reserved_;
+ auto old_size = size();
+ auto old_scratch_size = scratch_size();
+ reserved_ +=
+ (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
+ reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
+ if (buf_) {
+ buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
+ old_size, old_scratch_size);
+ } else {
+ buf_ = Allocate(allocator_, reserved_);
+ }
+ cur_ = buf_ + reserved_ - old_size;
+ scratch_ = buf_ + old_scratch_size;
+ }
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_VECTOR_DOWNWARD_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/verifier.h b/contrib/libs/flatbuffers/include/flatbuffers/verifier.h
new file mode 100644
index 0000000000..86dbcb4eac
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/verifier.h
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2021 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_VERIFIER_H_
+#define FLATBUFFERS_VERIFIER_H_
+
+#include "base.h"
+#include "vector.h"
+
+namespace flatbuffers {
+
+// Helper class to verify the integrity of a FlatBuffer
+class Verifier FLATBUFFERS_FINAL_CLASS {
+ public:
+ struct Options {
+ // The maximum nesting of tables and vectors before we call it invalid.
+ uoffset_t max_depth = 64;
+ // The maximum number of tables we will verify before we call it invalid.
+ uoffset_t max_tables = 1000000;
+ // If true, verify all data is aligned.
+ bool check_alignment = true;
+ // If true, run verifier on nested flatbuffers
+ bool check_nested_flatbuffers = true;
+ // The maximum size of a buffer.
+ size_t max_size = FLATBUFFERS_MAX_BUFFER_SIZE;
+ // Use assertions to check for errors.
+ bool assert = false;
+ };
+
+ explicit Verifier(const uint8_t *const buf, const size_t buf_len,
+ const Options &opts)
+ : buf_(buf), size_(buf_len), opts_(opts) {
+ FLATBUFFERS_ASSERT(size_ < opts.max_size);
+ }
+
+ // Deprecated API, please construct with Verifier::Options.
+ Verifier(const uint8_t *const buf, const size_t buf_len,
+ const uoffset_t max_depth = 64, const uoffset_t max_tables = 1000000,
+ const bool check_alignment = true)
+ : Verifier(buf, buf_len, [&] {
+ Options opts;
+ opts.max_depth = max_depth;
+ opts.max_tables = max_tables;
+ opts.check_alignment = check_alignment;
+ return opts;
+ }()) {}
+
+ // Central location where any verification failures register.
+ bool Check(const bool ok) const {
+ // clang-format off
+ #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
+ if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
+ #endif
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ if (!ok)
+ upper_bound_ = 0;
+ #endif
+ // clang-format on
+ return ok;
+ }
+
+ // Verify any range within the buffer.
+ bool Verify(const size_t elem, const size_t elem_len) const {
+ // clang-format off
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ auto upper_bound = elem + elem_len;
+ if (upper_bound_ < upper_bound)
+ upper_bound_ = upper_bound;
+ #endif
+ // clang-format on
+ return Check(elem_len < size_ && elem <= size_ - elem_len);
+ }
+
+ bool VerifyAlignment(const size_t elem, const size_t align) const {
+ return Check((elem & (align - 1)) == 0 || !opts_.check_alignment);
+ }
+
+ // Verify a range indicated by sizeof(T).
+ template<typename T> bool Verify(const size_t elem) const {
+ return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T));
+ }
+
+ bool VerifyFromPointer(const uint8_t *const p, const size_t len) {
+ return Verify(static_cast<size_t>(p - buf_), len);
+ }
+
+ // Verify relative to a known-good base pointer.
+ bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off,
+ const size_t elem_len, const size_t align) const {
+ const auto f = static_cast<size_t>(base - buf_) + elem_off;
+ return VerifyAlignment(f, align) && Verify(f, elem_len);
+ }
+
+ template<typename T>
+ bool VerifyField(const uint8_t *const base, const voffset_t elem_off,
+ const size_t align) const {
+ const auto f = static_cast<size_t>(base - buf_) + elem_off;
+ return VerifyAlignment(f, align) && Verify(f, sizeof(T));
+ }
+
+ // Verify a pointer (may be NULL) of a table type.
+ template<typename T> bool VerifyTable(const T *const table) {
+ return !table || table->Verify(*this);
+ }
+
+ // Verify a pointer (may be NULL) of any vector type.
+ template<int &..., typename T, typename LenT>
+ bool VerifyVector(const Vector<T, LenT> *const vec) const {
+ return !vec || VerifyVectorOrString<LenT>(
+ reinterpret_cast<const uint8_t *>(vec), sizeof(T));
+ }
+
+ // Verify a pointer (may be NULL) of a vector to struct.
+ template<int &..., typename T, typename LenT>
+ bool VerifyVector(const Vector<const T *, LenT> *const vec) const {
+ return VerifyVector(reinterpret_cast<const Vector<T, LenT> *>(vec));
+ }
+
+ // Verify a pointer (may be NULL) to string.
+ bool VerifyString(const String *const str) const {
+ size_t end;
+ return !str || (VerifyVectorOrString<uoffset_t>(
+ reinterpret_cast<const uint8_t *>(str), 1, &end) &&
+ Verify(end, 1) && // Must have terminator
+ Check(buf_[end] == '\0')); // Terminating byte must be 0.
+ }
+
+ // Common code between vectors and strings.
+ template<typename LenT = uoffset_t>
+ bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
+ size_t *const end = nullptr) const {
+ const auto vec_offset = static_cast<size_t>(vec - buf_);
+ // Check we can read the size field.
+ if (!Verify<LenT>(vec_offset)) return false;
+ // Check the whole array. If this is a string, the byte past the array must
+ // be 0.
+ const LenT size = ReadScalar<LenT>(vec);
+ const auto max_elems = opts_.max_size / elem_size;
+ if (!Check(size < max_elems))
+ return false; // Protect against byte_size overflowing.
+ const auto byte_size = sizeof(LenT) + elem_size * size;
+ if (end) *end = vec_offset + byte_size;
+ return Verify(vec_offset, byte_size);
+ }
+
+ // Special case for string contents, after the above has been called.
+ bool VerifyVectorOfStrings(const Vector<Offset<String>> *const vec) const {
+ if (vec) {
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ if (!VerifyString(vec->Get(i))) return false;
+ }
+ }
+ return true;
+ }
+
+ // Special case for table contents, after the above has been called.
+ template<typename T>
+ bool VerifyVectorOfTables(const Vector<Offset<T>> *const vec) {
+ if (vec) {
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ if (!vec->Get(i)->Verify(*this)) return false;
+ }
+ }
+ return true;
+ }
+
+ __suppress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
+ const uint8_t *const table) {
+ // Check the vtable offset.
+ const auto tableo = static_cast<size_t>(table - buf_);
+ if (!Verify<soffset_t>(tableo)) return false;
+ // This offset may be signed, but doing the subtraction unsigned always
+ // gives the result we want.
+ const auto vtableo =
+ tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
+ // Check the vtable size field, then check vtable fits in its entirety.
+ if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) &&
+ VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo),
+ sizeof(voffset_t))))
+ return false;
+ const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo);
+ return Check((vsize & 1) == 0) && Verify(vtableo, vsize);
+ }
+
+ template<typename T>
+ bool VerifyBufferFromStart(const char *const identifier, const size_t start) {
+ // Buffers have to be of some size to be valid. The reason it is a runtime
+ // check instead of static_assert, is that nested flatbuffers go through
+ // this call and their size is determined at runtime.
+ if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
+
+ // If an identifier is provided, check that we have a buffer
+ if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
+ BufferHasIdentifier(buf_ + start, identifier)))) {
+ return false;
+ }
+
+ // Call T::Verify, which must be in the generated code for this type.
+ const auto o = VerifyOffset<uoffset_t>(start);
+ return Check(o != 0) &&
+ reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
+ // clang-format off
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ && GetComputedSize()
+ #endif
+ ;
+ // clang-format on
+ }
+
+ template<typename T, int &..., typename SizeT>
+ bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT> *const buf,
+ const char *const identifier) {
+ // Caller opted out of this.
+ if (!opts_.check_nested_flatbuffers) return true;
+
+ // An empty buffer is OK as it indicates not present.
+ if (!buf) return true;
+
+ // If there is a nested buffer, it must be greater than the min size.
+ if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
+
+ Verifier nested_verifier(buf->data(), buf->size(), opts_);
+ return nested_verifier.VerifyBuffer<T>(identifier);
+ }
+
+ // Verify this whole buffer, starting with root type T.
+ template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
+
+ template<typename T> bool VerifyBuffer(const char *const identifier) {
+ return VerifyBufferFromStart<T>(identifier, 0);
+ }
+
+ template<typename T, typename SizeT = uoffset_t>
+ bool VerifySizePrefixedBuffer(const char *const identifier) {
+ return Verify<SizeT>(0U) &&
+ Check(ReadScalar<SizeT>(buf_) == size_ - sizeof(SizeT)) &&
+ VerifyBufferFromStart<T>(identifier, sizeof(SizeT));
+ }
+
+ template<typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
+ size_t VerifyOffset(const size_t start) const {
+ if (!Verify<OffsetT>(start)) return 0;
+ const auto o = ReadScalar<OffsetT>(buf_ + start);
+ // May not point to itself.
+ if (!Check(o != 0)) return 0;
+ // Can't wrap around larger than the max size.
+ if (!Check(static_cast<SOffsetT>(o) >= 0)) return 0;
+ // Must be inside the buffer to create a pointer from it (pointer outside
+ // buffer is UB).
+ if (!Verify(start + o, 1)) return 0;
+ return o;
+ }
+
+ template<typename OffsetT = uoffset_t>
+ size_t VerifyOffset(const uint8_t *const base, const voffset_t start) const {
+ return VerifyOffset<OffsetT>(static_cast<size_t>(base - buf_) + start);
+ }
+
+ // 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_ <= opts_.max_depth && num_tables_ <= opts_.max_tables);
+ }
+
+ // Called at the end of a table to pop the depth count.
+ bool EndTable() {
+ depth_--;
+ return true;
+ }
+
+ // Returns the message size in bytes
+ size_t GetComputedSize() const {
+ // clang-format off
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ uintptr_t size = upper_bound_;
+ // Align the size to uoffset_t
+ size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
+ return (size > size_) ? 0 : size;
+ #else
+ // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
+ (void)upper_bound_;
+ FLATBUFFERS_ASSERT(false);
+ return 0;
+ #endif
+ // clang-format on
+ }
+
+ std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
+
+ void SetFlexReuseTracker(std::vector<uint8_t> *const rt) {
+ flex_reuse_tracker_ = rt;
+ }
+
+ private:
+ const uint8_t *buf_;
+ const size_t size_;
+ const Options opts_;
+
+ mutable size_t upper_bound_ = 0;
+
+ uoffset_t depth_ = 0;
+ uoffset_t num_tables_ = 0;
+ std::vector<uint8_t> *flex_reuse_tracker_ = nullptr;
+};
+
+// Specialization for 64-bit offsets.
+template<>
+inline size_t Verifier::VerifyOffset<uoffset64_t>(const size_t start) const {
+ return VerifyOffset<uoffset64_t, soffset64_t>(start);
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_VERIFIER_H_
diff --git a/contrib/libs/flatbuffers/src/annotated_binary_text_gen.cpp b/contrib/libs/flatbuffers/src/annotated_binary_text_gen.cpp
new file mode 100644
index 0000000000..3967066b16
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/annotated_binary_text_gen.cpp
@@ -0,0 +1,461 @@
+#include "annotated_binary_text_gen.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <fstream>
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include "binary_annotator.h"
+#include "flatbuffers/base.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace {
+
+struct OutputConfig {
+ size_t largest_type_string = 10;
+
+ size_t largest_value_string = 20;
+
+ size_t max_bytes_per_line = 8;
+
+ size_t offset_max_char = 4;
+
+ char delimiter = '|';
+
+ bool include_vector_contents = true;
+};
+
+static std::string ToString(const BinarySectionType type) {
+ switch (type) {
+ case BinarySectionType::Header: return "header";
+ case BinarySectionType::Table: return "table";
+ case BinarySectionType::RootTable: return "root_table";
+ case BinarySectionType::VTable: return "vtable";
+ case BinarySectionType::Struct: return "struct";
+ case BinarySectionType::String: return "string";
+ case BinarySectionType::Vector: return "vector";
+ case BinarySectionType::Vector64: return "vector64";
+ case BinarySectionType::Unknown: return "unknown";
+ case BinarySectionType::Union: return "union";
+ case BinarySectionType::Padding: return "padding";
+ default: return "todo";
+ }
+}
+
+static bool IsOffset(const BinaryRegionType type) {
+ return type == BinaryRegionType::UOffset ||
+ type == BinaryRegionType::SOffset ||
+ type == BinaryRegionType::UOffset64;
+}
+
+template<typename T> std::string ToString(T value) {
+ if (std::is_floating_point<T>::value) {
+ std::stringstream ss;
+ ss << value;
+ return ss.str();
+ } else {
+ return std::to_string(value);
+ }
+}
+
+template<typename T>
+std::string ToValueString(const BinaryRegion &region, const uint8_t *binary) {
+ std::string s;
+ s += "0x";
+ const T val = ReadScalar<T>(binary + region.offset);
+ const uint64_t start_index = region.offset + region.length - 1;
+ for (uint64_t i = 0; i < region.length; ++i) {
+ s += ToHex(binary[start_index - i]);
+ }
+ s += " (";
+ s += ToString(val);
+ s += ")";
+ return s;
+}
+
+template<>
+std::string ToValueString<std::string>(const BinaryRegion &region,
+ const uint8_t *binary) {
+ return std::string(reinterpret_cast<const char *>(binary + region.offset),
+ static_cast<size_t>(region.array_length));
+}
+
+static std::string ToValueString(const BinaryRegion &region,
+ const uint8_t *binary,
+ const OutputConfig &output_config) {
+ std::string s;
+
+ if (region.array_length) {
+ if (region.type == BinaryRegionType::Uint8 ||
+ region.type == BinaryRegionType::Unknown) {
+ // Interpret each value as a ASCII to aid debugging
+ for (uint64_t i = 0; i < region.array_length; ++i) {
+ const uint8_t c = *(binary + region.offset + i);
+ s += isprint(c) ? static_cast<char>(c & 0x7F) : '.';
+ }
+ return s;
+ } else if (region.type == BinaryRegionType::Char) {
+ // string value
+ return ToValueString<std::string>(region, binary);
+ }
+ }
+
+ switch (region.type) {
+ case BinaryRegionType::Uint32:
+ return ToValueString<uint32_t>(region, binary);
+ case BinaryRegionType::Int32: return ToValueString<int32_t>(region, binary);
+ case BinaryRegionType::Uint16:
+ return ToValueString<uint16_t>(region, binary);
+ case BinaryRegionType::Int16: return ToValueString<int16_t>(region, binary);
+ case BinaryRegionType::Bool: return ToValueString<bool>(region, binary);
+ case BinaryRegionType::Uint8: return ToValueString<uint8_t>(region, binary);
+ case BinaryRegionType::Char: return ToValueString<char>(region, binary);
+ case BinaryRegionType::Byte:
+ case BinaryRegionType::Int8: return ToValueString<int8_t>(region, binary);
+ case BinaryRegionType::Int64: return ToValueString<int64_t>(region, binary);
+ case BinaryRegionType::Uint64:
+ return ToValueString<uint64_t>(region, binary);
+ case BinaryRegionType::Double: return ToValueString<double>(region, binary);
+ case BinaryRegionType::Float: return ToValueString<float>(region, binary);
+ case BinaryRegionType::UType: return ToValueString<uint8_t>(region, binary);
+
+ // Handle Offsets separately, incase they add additional details.
+ case BinaryRegionType::UOffset64:
+ s += ToValueString<uint64_t>(region, binary);
+ break;
+ case BinaryRegionType::UOffset:
+ s += ToValueString<uint32_t>(region, binary);
+ break;
+ case BinaryRegionType::SOffset:
+ s += ToValueString<int32_t>(region, binary);
+ break;
+ case BinaryRegionType::VOffset:
+ s += ToValueString<uint16_t>(region, binary);
+ break;
+
+ default: break;
+ }
+ // If this is an offset type, include the calculated offset location in the
+ // value.
+ // TODO(dbaileychess): It might be nicer to put this in the comment field.
+ if (IsOffset(region.type)) {
+ s += " Loc: 0x";
+ s += ToHex(region.points_to_offset, output_config.offset_max_char);
+ }
+ return s;
+}
+
+struct DocContinuation {
+ // The start column where the value text first starts
+ size_t value_start_column = 0;
+
+ // The remaining part of the doc to print.
+ std::string value;
+};
+
+static std::string GenerateTypeString(const BinaryRegion &region) {
+ return ToString(region.type) +
+ ((region.array_length)
+ ? "[" + std::to_string(region.array_length) + "]"
+ : "");
+}
+
+static std::string GenerateComment(const BinaryRegionComment &comment,
+ const BinarySection &) {
+ std::string s;
+ switch (comment.type) {
+ case BinaryRegionCommentType::Unknown: s = "unknown"; break;
+ case BinaryRegionCommentType::SizePrefix: s = "size prefix"; break;
+ case BinaryRegionCommentType::RootTableOffset:
+ s = "offset to root table `" + comment.name + "`";
+ break;
+ // TODO(dbaileychess): make this lowercase to follow the convention.
+ case BinaryRegionCommentType::FileIdentifier: s = "File Identifier"; break;
+ case BinaryRegionCommentType::Padding: s = "padding"; break;
+ case BinaryRegionCommentType::VTableSize: s = "size of this vtable"; break;
+ case BinaryRegionCommentType::VTableRefferingTableLength:
+ s = "size of referring table";
+ break;
+ case BinaryRegionCommentType::VTableFieldOffset:
+ s = "offset to field `" + comment.name;
+ break;
+ case BinaryRegionCommentType::VTableUnknownFieldOffset:
+ s = "offset to unknown field (id: " + std::to_string(comment.index) + ")";
+ break;
+
+ case BinaryRegionCommentType::TableVTableOffset:
+ s = "offset to vtable";
+ break;
+ case BinaryRegionCommentType::TableField:
+ s = "table field `" + comment.name;
+ break;
+ case BinaryRegionCommentType::TableUnknownField: s = "unknown field"; break;
+ case BinaryRegionCommentType::TableOffsetField:
+ s = "offset to field `" + comment.name + "`";
+ break;
+ case BinaryRegionCommentType::StructField:
+ s = "struct field `" + comment.name + "`";
+ break;
+ case BinaryRegionCommentType::ArrayField:
+ s = "array field `" + comment.name + "`[" +
+ std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::StringLength: s = "length of string"; break;
+ case BinaryRegionCommentType::StringValue: s = "string literal"; break;
+ case BinaryRegionCommentType::StringTerminator:
+ s = "string terminator";
+ break;
+ case BinaryRegionCommentType::VectorLength:
+ s = "length of vector (# items)";
+ break;
+ case BinaryRegionCommentType::VectorValue:
+ s = "value[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorTableValue:
+ s = "offset to table[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorStringValue:
+ s = "offset to string[" + std::to_string(comment.index) + "]";
+ break;
+ case BinaryRegionCommentType::VectorUnionValue:
+ s = "offset to union[" + std::to_string(comment.index) + "]";
+ break;
+
+ default: break;
+ }
+ if (!comment.default_value.empty()) { s += " " + comment.default_value; }
+
+ switch (comment.status) {
+ case BinaryRegionStatus::OK: break; // no-op
+ case BinaryRegionStatus::WARN: s = "WARN: " + s; break;
+ case BinaryRegionStatus::WARN_NO_REFERENCES:
+ s = "WARN: nothing refers to this section.";
+ break;
+ case BinaryRegionStatus::WARN_CORRUPTED_PADDING:
+ s = "WARN: could be corrupted padding region.";
+ break;
+ case BinaryRegionStatus::WARN_PADDING_LENGTH:
+ s = "WARN: padding is longer than expected.";
+ break;
+ case BinaryRegionStatus::ERROR: s = "ERROR: " + s; break;
+ case BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY:
+ s = "ERROR: " + s + ". Invalid offset, points outside the binary.";
+ break;
+ case BinaryRegionStatus::ERROR_INCOMPLETE_BINARY:
+ s = "ERROR: " + s + ". Incomplete binary, expected to read " +
+ comment.status_message + " bytes.";
+ break;
+ case BinaryRegionStatus::ERROR_LENGTH_TOO_LONG:
+ s = "ERROR: " + s + ". Longer than the binary.";
+ break;
+ case BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT:
+ s = "ERROR: " + s + ". Shorter than the minimum length: ";
+ break;
+ case BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT:
+ s = "ERROR: " + s + ". Required field is not present.";
+ break;
+ case BinaryRegionStatus::ERROR_INVALID_UNION_TYPE:
+ s = "ERROR: " + s + ". Invalid union type value.";
+ break;
+ case BinaryRegionStatus::ERROR_CYCLE_DETECTED:
+ s = "ERROR: " + s + ". Invalid offset, cycle detected.";
+ break;
+ }
+
+ return s;
+}
+
+static void GenerateDocumentation(std::ostream &os, const BinaryRegion &region,
+ const BinarySection &section,
+ const uint8_t *binary,
+ DocContinuation &continuation,
+ const OutputConfig &output_config) {
+ // Check if there is a doc continuation that should be prioritized.
+ if (continuation.value_start_column) {
+ os << std::string(continuation.value_start_column - 2, ' ');
+ os << output_config.delimiter << " ";
+
+ os << continuation.value.substr(0, output_config.max_bytes_per_line);
+ continuation.value = continuation.value.substr(
+ std::min(output_config.max_bytes_per_line, continuation.value.size()));
+ return;
+ }
+
+ size_t size_of = 0;
+ {
+ std::stringstream ss;
+ ss << std::setw(static_cast<int>(output_config.largest_type_string))
+ << std::left;
+ ss << GenerateTypeString(region);
+ os << ss.str();
+ size_of = ss.str().size();
+ }
+ os << " " << output_config.delimiter << " ";
+ if (region.array_length) {
+ // Record where the value is first being outputted.
+ continuation.value_start_column = 3 + size_of;
+
+ // Get the full-length value, which we will chunk below.
+ const std::string value = ToValueString(region, binary, output_config);
+
+ std::stringstream ss;
+ ss << std::setw(static_cast<int>(output_config.largest_value_string))
+ << std::left;
+ ss << value.substr(0, output_config.max_bytes_per_line);
+ os << ss.str();
+
+ continuation.value =
+ value.substr(std::min(output_config.max_bytes_per_line, value.size()));
+ } else {
+ std::stringstream ss;
+ ss << std::setw(static_cast<int>(output_config.largest_value_string))
+ << std::left;
+ ss << ToValueString(region, binary, output_config);
+ os << ss.str();
+ }
+
+ os << " " << output_config.delimiter << " ";
+ os << GenerateComment(region.comment, section);
+}
+
+static void GenerateRegion(std::ostream &os, const BinaryRegion &region,
+ const BinarySection &section, const uint8_t *binary,
+ const OutputConfig &output_config) {
+ bool doc_generated = false;
+ DocContinuation doc_continuation;
+ for (uint64_t i = 0; i < region.length; ++i) {
+ if ((i % output_config.max_bytes_per_line) == 0) {
+ // Start a new line of output
+ os << std::endl;
+ os << " +0x" << ToHex(region.offset + i, output_config.offset_max_char);
+ os << " " << output_config.delimiter;
+ }
+
+ // Add each byte
+ os << " " << ToHex(binary[region.offset + i]);
+
+ // Check for end of line or end of region conditions.
+ if (((i + 1) % output_config.max_bytes_per_line == 0) ||
+ i + 1 == region.length) {
+ if (i + 1 == region.length) {
+ // We are out of bytes but haven't the kMaxBytesPerLine, so we need to
+ // zero those out to align everything globally.
+ for (uint64_t j = i + 1; (j % output_config.max_bytes_per_line) != 0;
+ ++j) {
+ os << " ";
+ }
+ }
+ os << " " << output_config.delimiter;
+ // This is the end of the first line or its the last byte of the region,
+ // generate the end-of-line documentation.
+ if (!doc_generated) {
+ os << " ";
+ GenerateDocumentation(os, region, section, binary, doc_continuation,
+ output_config);
+
+ // If we have a value in the doc continuation, that means the doc is
+ // being printed on multiple lines.
+ doc_generated = doc_continuation.value.empty();
+ }
+ }
+ }
+}
+
+static void GenerateSection(std::ostream &os, const BinarySection &section,
+ const uint8_t *binary,
+ const OutputConfig &output_config) {
+ os << std::endl;
+ os << ToString(section.type);
+ if (!section.name.empty()) { os << " (" + section.name + ")"; }
+ os << ":";
+
+ // As a space saving measure, skip generating every vector element, just put
+ // the first and last elements in the output. Skip the whole thing if there
+ // are only three or fewer elements, as it doesn't save space.
+ if ((section.type == BinarySectionType::Vector ||
+ section.type == BinarySectionType::Vector64) &&
+ !output_config.include_vector_contents && section.regions.size() > 4) {
+ // Generate the length region which should be first.
+ GenerateRegion(os, section.regions[0], section, binary, output_config);
+
+ // Generate the first element.
+ GenerateRegion(os, section.regions[1], section, binary, output_config);
+
+ // Indicate that we omitted elements.
+ os << std::endl
+ << " <" << section.regions.size() - 3 << " regions omitted>";
+
+ // Generate the last element.
+ GenerateRegion(os, section.regions.back(), section, binary, output_config);
+ os << std::endl;
+ return;
+ }
+
+ for (const BinaryRegion &region : section.regions) {
+ GenerateRegion(os, region, section, binary, output_config);
+ }
+ os << std::endl;
+}
+} // namespace
+
+bool AnnotatedBinaryTextGenerator::Generate(
+ const std::string &filename, const std::string &schema_filename) {
+ OutputConfig output_config;
+ output_config.max_bytes_per_line = options_.max_bytes_per_line;
+ output_config.include_vector_contents = options_.include_vector_contents;
+
+ // Given the length of the binary, we can calculate the maximum number of
+ // characters to display in the offset hex: (i.e. 2 would lead to 0XFF being
+ // the max output).
+ output_config.offset_max_char =
+ binary_length_ > 0xFFFFFF
+ ? 8
+ : (binary_length_ > 0xFFFF ? 6 : (binary_length_ > 0xFF ? 4 : 2));
+
+ // Find the largest type string of all the regions in this file, so we can
+ // align the output nicely.
+ output_config.largest_type_string = 0;
+ for (const auto &section : annotations_) {
+ for (const auto &region : section.second.regions) {
+ std::string s = GenerateTypeString(region);
+ if (s.size() > output_config.largest_type_string) {
+ output_config.largest_type_string = s.size();
+ }
+
+ // Don't consider array regions, as they will be split to multiple lines.
+ if (!region.array_length) {
+ s = ToValueString(region, binary_, output_config);
+ if (s.size() > output_config.largest_value_string) {
+ output_config.largest_value_string = s.size();
+ }
+ }
+ }
+ }
+
+ // Modify the output filename.
+ std::string output_filename = StripExtension(filename);
+ output_filename += options_.output_postfix;
+ output_filename +=
+ "." + (options_.output_extension.empty() ? GetExtension(filename)
+ : options_.output_extension);
+
+ std::ofstream ofs(output_filename.c_str());
+
+ ofs << "// Annotated Flatbuffer Binary" << std::endl;
+ ofs << "//" << std::endl;
+ ofs << "// Schema file: " << schema_filename << std::endl;
+ ofs << "// Binary file: " << filename << std::endl;
+
+ // Generate each of the binary sections
+ for (const auto &section : annotations_) {
+ GenerateSection(ofs, section.second, binary_, output_config);
+ }
+
+ ofs.close();
+ return true;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/annotated_binary_text_gen.h b/contrib/libs/flatbuffers/src/annotated_binary_text_gen.h
new file mode 100644
index 0000000000..a0806d88a0
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/annotated_binary_text_gen.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 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_ANNOTATED_BINARY_TEXT_GEN_H_
+#define FLATBUFFERS_ANNOTATED_BINARY_TEXT_GEN_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "binary_annotator.h"
+
+namespace flatbuffers {
+
+class AnnotatedBinaryTextGenerator {
+ public:
+ struct Options {
+ // The maximum number of raw bytes to print per line in the output. 8 is a
+ // good default due to the largest type (double) being 8 bytes long.
+ size_t max_bytes_per_line = 8;
+
+ // The output file postfix, appended between the filename and the extension.
+ // Example binary1.bin -> binary1_annotated.bin
+ std::string output_postfix = "";
+
+ // The output file extension, replacing any extension given. If empty, don't
+ // change the provided extension. AFB = Annotated Flatbuffer Binary
+ //
+ // Example: binary1.bin -> binary1.afb
+ std::string output_extension = "afb";
+
+ // Controls.
+ bool include_vector_contents = true;
+ };
+
+ explicit AnnotatedBinaryTextGenerator(
+ const Options &options, std::map<uint64_t, BinarySection> annotations,
+ const uint8_t *const binary, const int64_t binary_length)
+ : annotations_(std::move(annotations)),
+ binary_(binary),
+ binary_length_(binary_length),
+ options_(options) {}
+
+ // Generate the annotated binary for the given `filename`. Returns true if the
+ // annotated binary was successfully saved.
+ bool Generate(const std::string &filename,
+ const std::string &schema_filename);
+
+ private:
+ const std::map<uint64_t, BinarySection> annotations_;
+
+ // The binary data itself.
+ const uint8_t *binary_;
+ const int64_t binary_length_;
+
+ // Output configuration
+ const Options options_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_ANNOTATED_BINARY_TEXT_GEN_H_
diff --git a/contrib/libs/flatbuffers/src/bfbs_gen.h b/contrib/libs/flatbuffers/src/bfbs_gen.h
new file mode 100644
index 0000000000..ed20dc8965
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_gen.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2021 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_BFBS_GEN_H_
+#define FLATBUFFERS_BFBS_GEN_H_
+
+#include <cstdint>
+
+#include "flatbuffers/code_generator.h"
+#include "flatbuffers/reflection_generated.h"
+
+namespace flatbuffers {
+
+namespace {
+
+static void ForAllEnums(
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums,
+ std::function<void(const reflection::Enum *)> func) {
+ for (auto it = enums->cbegin(); it != enums->cend(); ++it) { func(*it); }
+}
+
+static void ForAllObjects(
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects,
+ std::function<void(const reflection::Object *)> func) {
+ for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
+}
+
+static void ForAllEnumValues(
+ const reflection::Enum *enum_def,
+ std::function<void(const reflection::EnumVal *)> func) {
+ for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
+ ++it) {
+ func(*it);
+ }
+}
+
+static void ForAllDocumentation(
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
+ *documentation,
+ std::function<void(const flatbuffers::String *)> func) {
+ if (!documentation) { return; }
+ for (auto it = documentation->cbegin(); it != documentation->cend(); ++it) {
+ func(*it);
+ }
+}
+
+// Maps the field index into object->fields() to the field's ID (the ith element
+// in the return vector).
+static std::vector<uint32_t> FieldIdToIndex(const reflection::Object *object) {
+ std::vector<uint32_t> field_index_by_id;
+ field_index_by_id.resize(object->fields()->size());
+
+ // Create the mapping of field ID to the index into the vector.
+ for (uint32_t i = 0; i < object->fields()->size(); ++i) {
+ auto field = object->fields()->Get(i);
+ field_index_by_id[field->id()] = i;
+ }
+
+ return field_index_by_id;
+}
+
+static bool IsStructOrTable(const reflection::BaseType base_type) {
+ return base_type == reflection::Obj;
+}
+
+static bool IsFloatingPoint(const reflection::BaseType base_type) {
+ return base_type == reflection::Float || base_type == reflection::Double;
+}
+
+static bool IsBool(const reflection::BaseType base_type) {
+ return base_type == reflection::Bool;
+}
+
+static bool IsSingleByte(const reflection::BaseType base_type) {
+ return base_type >= reflection::UType && base_type <= reflection::UByte;
+}
+
+static bool IsVector(const reflection::BaseType base_type) {
+ return base_type == reflection::Vector;
+}
+
+} // namespace
+
+// A concrete base Flatbuffer Generator that specific language generators can
+// derive from.
+class BaseBfbsGenerator : public CodeGenerator {
+ public:
+ virtual ~BaseBfbsGenerator() {}
+ BaseBfbsGenerator() : schema_(nullptr) {}
+
+ virtual Status GenerateFromSchema(
+ const reflection::Schema *schema) = 0;
+
+ virtual uint64_t SupportedAdvancedFeatures() const = 0;
+
+ // Override of the Generator::GenerateCode method that does the initial
+ // deserialization and verification steps.
+ Status GenerateCode(const uint8_t *buffer,
+ int64_t length) FLATBUFFERS_OVERRIDE {
+ flatbuffers::Verifier verifier(buffer, static_cast<size_t>(length));
+ if (!reflection::VerifySchemaBuffer(verifier)) {
+ return FAILED_VERIFICATION;
+ }
+
+ // Store the root schema since there are cases where leaf nodes refer to
+ // things in the root schema (e.g., indexing the objects).
+ schema_ = reflection::GetSchema(buffer);
+
+ const uint64_t advance_features = schema_->advanced_features();
+ if (advance_features > SupportedAdvancedFeatures()) {
+ return FAILED_VERIFICATION;
+ }
+
+ Status status = GenerateFromSchema(schema_);
+ schema_ = nullptr;
+ return status;
+ }
+
+ protected:
+ // GetObject returns the underlying object struct of the given type
+ // if element_type is true and GetObject is a list of objects then
+ // GetObject will correctly return the object struct of the vector's elements
+ const reflection::Object *GetObject(const reflection::Type *type,
+ bool element_type = false) const {
+ const reflection::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (type->index() >= 0 && IsStructOrTable(base_type)) {
+ return GetObjectByIndex(type->index());
+ }
+ return nullptr;
+ }
+
+ // GetEnum returns the underlying enum struct of the given type
+ // if element_type is true and GetEnum is a list of enums then
+ // GetEnum will correctly return the enum struct of the vector's elements
+ const reflection::Enum *GetEnum(const reflection::Type *type,
+ bool element_type = false) const {
+ const reflection::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ // TODO(derekbailey): it would be better to have a explicit list of allowed
+ // base types, instead of negating Obj types.
+ if (type->index() >= 0 && !IsStructOrTable(base_type)) {
+ return GetEnumByIndex(type->index());
+ }
+ return nullptr;
+ }
+
+ // Used to get a object that is reference by index. (e.g.
+ // reflection::Type::index). Returns nullptr if no object is available.
+ const reflection::Object *GetObjectByIndex(int32_t index) const {
+ if (!schema_ || index < 0 ||
+ index >= static_cast<int32_t>(schema_->objects()->size())) {
+ return nullptr;
+ }
+ return schema_->objects()->Get(index);
+ }
+
+ // Used to get a enum that is reference by index. (e.g.
+ // reflection::Type::index). Returns nullptr if no enum is available.
+ const reflection::Enum *GetEnumByIndex(int32_t index) const {
+ if (!schema_ || index < 0 ||
+ index >= static_cast<int32_t>(schema_->enums()->size())) {
+ return nullptr;
+ }
+ return schema_->enums()->Get(index);
+ }
+
+ void ForAllFields(const reflection::Object *object, bool reverse,
+ std::function<void(const reflection::Field *)> func) const {
+ const std::vector<uint32_t> field_to_id_map = FieldIdToIndex(object);
+ for (size_t i = 0; i < field_to_id_map.size(); ++i) {
+ func(object->fields()->Get(
+ field_to_id_map[reverse ? field_to_id_map.size() - (i + 1) : i]));
+ }
+ }
+
+ bool IsTable(const reflection::Type *type, bool use_element = false) const {
+ return !IsStruct(type, use_element);
+ }
+
+ bool IsStruct(const reflection::Type *type, bool use_element = false) const {
+ const reflection::BaseType base_type =
+ use_element ? type->element() : type->base_type();
+ return IsStructOrTable(base_type) &&
+ GetObjectByIndex(type->index())->is_struct();
+ }
+
+ const reflection::Schema *schema_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_GEN_H_
diff --git a/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp b/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
new file mode 100644
index 0000000000..8823d912b1
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_gen_lua.cpp
@@ -0,0 +1,674 @@
+/*
+ * Copyright 2021 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 "bfbs_gen_lua.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+// Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
+#include "bfbs_gen.h"
+#include "bfbs_namer.h"
+
+// The intermediate representation schema.
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/reflection_generated.h"
+
+namespace flatbuffers {
+namespace {
+
+// To reduce typing
+namespace r = ::reflection;
+
+std::set<std::string> LuaKeywords() {
+ return { "and", "break", "do", "else", "elseif", "end",
+ "false", "for", "function", "goto", "if", "in",
+ "local", "nil", "not", "or", "repeat", "return",
+ "then", "true", "until", "while" };
+}
+
+Namer::Config LuaDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kUpperCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kUpperCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"__",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".lua" };
+}
+
+class LuaBfbsGenerator : public BaseBfbsGenerator {
+ public:
+ explicit LuaBfbsGenerator(const std::string &flatc_version)
+ : BaseBfbsGenerator(),
+ keywords_(),
+ requires_(),
+ current_obj_(nullptr),
+ current_enum_(nullptr),
+ flatc_version_(flatc_version),
+ namer_(LuaDefaultConfig(), LuaKeywords()) {}
+
+ Status GenerateFromSchema(const r::Schema *schema) FLATBUFFERS_OVERRIDE {
+ if (!GenerateEnums(schema->enums())) { return ERROR; }
+ if (!GenerateObjects(schema->objects(), schema->root_table())) {
+ return ERROR;
+ }
+ return OK;
+ }
+
+ using BaseBfbsGenerator::GenerateCode;
+
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) FLATBUFFERS_OVERRIDE {
+ if (!GenerateLua(parser, path, filename)) { return ERROR; }
+ return OK;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return true; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kLua; }
+
+ std::string LanguageName() const override { return "Lua"; }
+
+ uint64_t SupportedAdvancedFeatures() const FLATBUFFERS_OVERRIDE {
+ return 0xF;
+ }
+
+ protected:
+ bool GenerateEnums(
+ const flatbuffers::Vector<flatbuffers::Offset<r::Enum>> *enums) {
+ ForAllEnums(enums, [&](const r::Enum *enum_def) {
+ std::string code;
+
+ StartCodeBlock(enum_def);
+
+ std::string ns;
+ const std::string enum_name =
+ namer_.Type(namer_.Denamespace(enum_def, ns));
+
+ GenerateDocumentation(enum_def->documentation(), "", code);
+ code += "local " + enum_name + " = {\n";
+
+ ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
+ GenerateDocumentation(enum_val->documentation(), " ", code);
+ code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
+ NumToString(enum_val->value()) + ",\n";
+ });
+ code += "}\n";
+ code += "\n";
+
+ EmitCodeBlock(code, enum_name, ns, enum_def->declaration_file()->str());
+ });
+ return true;
+ }
+
+ bool GenerateObjects(
+ const flatbuffers::Vector<flatbuffers::Offset<r::Object>> *objects,
+ const r::Object *root_object) {
+ ForAllObjects(objects, [&](const r::Object *object) {
+ std::string code;
+
+ StartCodeBlock(object);
+
+ // Register the main flatbuffers module.
+ RegisterRequires("flatbuffers", "flatbuffers");
+
+ std::string ns;
+ const std::string object_name =
+ namer_.Type(namer_.Denamespace(object, ns));
+
+ GenerateDocumentation(object->documentation(), "", code);
+
+ code += "local " + object_name + " = {}\n";
+ code += "local mt = {}\n";
+ code += "\n";
+ code += "function " + object_name + ".New()\n";
+ code += " local o = {}\n";
+ code += " setmetatable(o, {__index = mt})\n";
+ code += " return o\n";
+ code += "end\n";
+ code += "\n";
+
+ if (object == root_object) {
+ code += "function " + object_name + ".GetRootAs" + object_name +
+ "(buf, offset)\n";
+ code += " if type(buf) == \"string\" then\n";
+ code += " buf = flatbuffers.binaryArray.New(buf)\n";
+ code += " end\n";
+ code += "\n";
+ code += " local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
+ code += " local o = " + object_name + ".New()\n";
+ code += " o:Init(buf, n + offset)\n";
+ code += " return o\n";
+ code += "end\n";
+ code += "\n";
+ }
+
+ // Generates a init method that receives a pre-existing accessor object,
+ // so that objects can be reused.
+
+ code += "function mt:Init(buf, pos)\n";
+ code += " self.view = flatbuffers.view.New(buf, pos)\n";
+ code += "end\n";
+ code += "\n";
+
+ // Create all the field accessors.
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ // Skip writing deprecated fields altogether.
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const r::BaseType base_type = field->type()->base_type();
+
+ // Generate some fixed strings so we don't repeat outselves later.
+ const std::string getter_signature =
+ "function mt:" + field_name + "()\n";
+ const std::string offset_prefix = "local o = self.view:Offset(" +
+ NumToString(field->offset()) + ")\n";
+ const std::string offset_prefix_2 = "if o ~= 0 then\n";
+
+ GenerateDocumentation(field->documentation(), "", code);
+
+ if (IsScalar(base_type)) {
+ code += getter_signature;
+
+ if (object->is_struct()) {
+ // TODO(derekbailey): it would be nice to modify the view:Get to
+ // just pass in the offset and not have to add it its own
+ // self.view.pos.
+ code += " return " + GenerateGetter(field->type()) +
+ "self.view.pos + " + NumToString(field->offset()) + ")\n";
+ } else {
+ // Table accessors
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+
+ std::string getter =
+ GenerateGetter(field->type()) + "self.view.pos + o)";
+ if (IsBool(base_type)) { getter = "(" + getter + " ~=0)"; }
+ code += " return " + getter + "\n";
+ code += " end\n";
+ code += " return " + DefaultValue(field) + "\n";
+ }
+ code += "end\n";
+ code += "\n";
+ } else {
+ switch (base_type) {
+ case r::String: {
+ code += getter_signature;
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " return " + GenerateGetter(field->type()) +
+ "self.view.pos + o)\n";
+ code += " end\n";
+ code += "end\n";
+ code += "\n";
+ break;
+ }
+ case r::Obj: {
+ if (object->is_struct()) {
+ code += "function mt:" + field_name + "(obj)\n";
+ code += " obj:Init(self.view.bytes, self.view.pos + " +
+ NumToString(field->offset()) + ")\n";
+ code += " return obj\n";
+ code += "end\n";
+ code += "\n";
+ } else {
+ code += getter_signature;
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+
+ const r::Object *field_object = GetObject(field->type());
+ if (!field_object) {
+ // TODO(derekbailey): this is an error condition. we
+ // should report it better.
+ return;
+ }
+ code += " local x = " +
+ std::string(
+ field_object->is_struct()
+ ? "self.view.pos + o\n"
+ : "self.view:Indirect(self.view.pos + o)\n");
+ const std::string require_name = RegisterRequires(field);
+ code += " local obj = " + require_name + ".New()\n";
+ code += " obj:Init(self.view.bytes, x)\n";
+ code += " return obj\n";
+ code += " end\n";
+ code += "end\n";
+ code += "\n";
+ }
+ break;
+ }
+ case r::Union: {
+ code += getter_signature;
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code +=
+ " local obj = "
+ "flatbuffers.view.New(flatbuffers.binaryArray.New("
+ "0), 0)\n";
+ code += " " + GenerateGetter(field->type()) + "obj, o)\n";
+ code += " return obj\n";
+ code += " end\n";
+ code += "end\n";
+ code += "\n";
+ break;
+ }
+ case r::Array:
+ case r::Vector: {
+ const r::BaseType vector_base_type = field->type()->element();
+ int32_t element_size = field->type()->element_size();
+ code += "function mt:" + field_name + "(j)\n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+
+ if (IsStructOrTable(vector_base_type)) {
+ code += " local x = self.view:Vector(o)\n";
+ code +=
+ " x = x + ((j-1) * " + NumToString(element_size) + ")\n";
+ if (IsTable(field->type(), /*use_element=*/true)) {
+ code += " x = self.view:Indirect(x)\n";
+ } else {
+ // Vector of structs are inline, so we need to query the
+ // size of the struct.
+ const reflection::Object *obj =
+ GetObjectByIndex(field->type()->index());
+ element_size = obj->bytesize();
+ }
+
+ // Include the referenced type, thus we need to make sure
+ // we set `use_element` to true.
+ const std::string require_name =
+ RegisterRequires(field, /*use_element=*/true);
+ code += " local obj = " + require_name + ".New()\n";
+ code += " obj:Init(self.view.bytes, x)\n";
+ code += " return obj\n";
+ } else {
+ code += " local a = self.view:Vector(o)\n";
+ code += " return " + GenerateGetter(field->type()) +
+ "a + ((j-1) * " + NumToString(element_size) + "))\n";
+ }
+ code += " end\n";
+ // Only generate a default value for those types that are
+ // supported.
+ if (!IsStructOrTable(vector_base_type)) {
+ code +=
+ " return " +
+ std::string(vector_base_type == r::String ? "''\n" : "0\n");
+ }
+ code += "end\n";
+ code += "\n";
+
+ // If the vector is composed of single byte values, we
+ // generate a helper function to get it as a byte string in
+ // Lua.
+ if (IsSingleByte(vector_base_type)) {
+ code += "function mt:" + field_name + "AsString(start, stop)\n";
+ code += " return self.view:VectorAsString(" +
+ NumToString(field->offset()) + ", start, stop)\n";
+ code += "end\n";
+ code += "\n";
+ }
+
+ // We also make a new accessor to query just the length of the
+ // vector.
+ code += "function mt:" + field_name + "Length()\n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " return self.view:VectorLen(o)\n";
+ code += " end\n";
+ code += " return 0\n";
+ code += "end\n";
+ code += "\n";
+ break;
+ }
+ default: {
+ return;
+ }
+ }
+ }
+ return;
+ });
+
+ // Create all the builders
+ if (object->is_struct()) {
+ code += "function " + object_name + ".Create" + object_name +
+ "(builder" + GenerateStructBuilderArgs(object) + ")\n";
+ code += AppendStructBuilderBody(object);
+ code += " return builder:Offset()\n";
+ code += "end\n";
+ code += "\n";
+ } else {
+ // Table builders
+ code += "function " + object_name + ".Start(builder)\n";
+ code += " builder:StartObject(" +
+ NumToString(object->fields()->size()) + ")\n";
+ code += "end\n";
+ code += "\n";
+
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const std::string variable_name = namer_.Variable(*field);
+
+ code += "function " + object_name + ".Add" + field_name +
+ "(builder, " + variable_name + ")\n";
+ code += " builder:Prepend" + GenerateMethod(field) + "Slot(" +
+ NumToString(field->id()) + ", " + variable_name + ", " +
+ DefaultValue(field) + ")\n";
+ code += "end\n";
+ code += "\n";
+
+ if (IsVector(field->type()->base_type())) {
+ code += "function " + object_name + ".Start" + field_name +
+ "Vector(builder, numElems)\n";
+
+ const int32_t element_size = field->type()->element_size();
+ int32_t alignment = 0;
+ if (IsStruct(field->type(), /*use_element=*/true)) {
+ alignment = GetObjectByIndex(field->type()->index())->minalign();
+ } else {
+ alignment = element_size;
+ }
+
+ code += " return builder:StartVector(" +
+ NumToString(element_size) + ", numElems, " +
+ NumToString(alignment) + ")\n";
+ code += "end\n";
+ code += "\n";
+ }
+ });
+
+ code += "function " + object_name + ".End(builder)\n";
+ code += " return builder:EndObject()\n";
+ code += "end\n";
+ code += "\n";
+ }
+
+ EmitCodeBlock(code, object_name, ns, object->declaration_file()->str());
+ });
+ return true;
+ }
+
+ private:
+ void GenerateDocumentation(
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
+ *documentation,
+ std::string indent, std::string &code) const {
+ flatbuffers::ForAllDocumentation(
+ documentation, [&](const flatbuffers::String *str) {
+ code += indent + "--" + str->str() + "\n";
+ });
+ }
+
+ std::string GenerateStructBuilderArgs(const r::Object *object,
+ std::string prefix = "") const {
+ std::string signature;
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ signature += GenerateStructBuilderArgs(
+ field_object, prefix + namer_.Variable(*field) + "_");
+ } else {
+ signature += ", " + prefix + namer_.Variable(*field);
+ }
+ });
+ return signature;
+ }
+
+ std::string AppendStructBuilderBody(const r::Object *object,
+ std::string prefix = "") const {
+ std::string code;
+ code += " builder:Prep(" + NumToString(object->minalign()) + ", " +
+ NumToString(object->bytesize()) + ")\n";
+
+ // We need to reverse the order we iterate over, since we build the
+ // buffer backwards.
+ ForAllFields(object, /*reverse=*/true, [&](const r::Field *field) {
+ const int32_t num_padding_bytes = field->padding();
+ if (num_padding_bytes) {
+ code += " builder:Pad(" + NumToString(num_padding_bytes) + ")\n";
+ }
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ code += AppendStructBuilderBody(field_object,
+ prefix + namer_.Variable(*field) + "_");
+ } else {
+ code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
+ namer_.Variable(*field) + ")\n";
+ }
+ });
+
+ return code;
+ }
+
+ std::string GenerateMethod(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsScalar(base_type)) { return namer_.Type(GenerateType(base_type)); }
+ if (IsStructOrTable(base_type)) { return "Struct"; }
+ return "UOffsetTRelative";
+ }
+
+ std::string GenerateGetter(const r::Type *type,
+ bool element_type = false) const {
+ switch (element_type ? type->element() : type->base_type()) {
+ case r::String: return "self.view:String(";
+ case r::Union: return "self.view:Union(";
+ case r::Vector: return GenerateGetter(type, true);
+ default:
+ return "self.view:Get(flatbuffers.N." +
+ namer_.Type(GenerateType(type, element_type)) + ", ";
+ }
+ }
+
+ std::string GenerateType(const r::Type *type,
+ bool element_type = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (IsScalar(base_type)) { return GenerateType(base_type); }
+ switch (base_type) {
+ case r::String: return "string";
+ case r::Vector: return GenerateGetter(type, true);
+ case r::Obj: return namer_.Type(namer_.Denamespace(GetObject(type)));
+
+ default: return "*flatbuffers.Table";
+ }
+ }
+
+ std::string GenerateType(const r::BaseType base_type) const {
+ // Need to override the default naming to match the Lua runtime libraries.
+ // TODO(derekbailey): make overloads in the runtime libraries to avoid this.
+ switch (base_type) {
+ case r::None: return "uint8";
+ case r::UType: return "uint8";
+ case r::Byte: return "int8";
+ case r::UByte: return "uint8";
+ case r::Short: return "int16";
+ case r::UShort: return "uint16";
+ case r::Int: return "int32";
+ case r::UInt: return "uint32";
+ case r::Long: return "int64";
+ case r::ULong: return "uint64";
+ case r::Float: return "Float32";
+ case r::Double: return "Float64";
+ default: return r::EnumNameBaseType(base_type);
+ }
+ }
+
+ std::string DefaultValue(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsFloatingPoint(base_type)) {
+ return NumToString(field->default_real());
+ }
+ if (IsBool(base_type)) {
+ return field->default_integer() ? "true" : "false";
+ }
+ if (IsScalar(base_type)) { return NumToString((field->default_integer())); }
+ // represents offsets
+ return "0";
+ }
+
+ void StartCodeBlock(const reflection::Enum *enum_def) {
+ current_enum_ = enum_def;
+ current_obj_ = nullptr;
+ requires_.clear();
+ }
+
+ void StartCodeBlock(const reflection::Object *object) {
+ current_obj_ = object;
+ current_enum_ = nullptr;
+ requires_.clear();
+ }
+
+ std::string RegisterRequires(const r::Field *field,
+ bool use_element = false) {
+ std::string type_name;
+
+ const r::BaseType type =
+ use_element ? field->type()->element() : field->type()->base_type();
+
+ if (IsStructOrTable(type)) {
+ const r::Object *object = GetObjectByIndex(field->type()->index());
+ if (object == current_obj_) { return namer_.Denamespace(object); }
+ type_name = object->name()->str();
+ } else {
+ const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
+ if (enum_def == current_enum_) { return namer_.Denamespace(enum_def); }
+ type_name = enum_def->name()->str();
+ }
+
+ // Prefix with double __ to avoid name clashing, since these are defined
+ // at the top of the file and have lexical scoping. Replace '.' with '_'
+ // so it can be a legal identifier.
+ std::string name = "__" + type_name;
+ std::replace(name.begin(), name.end(), '.', '_');
+
+ return RegisterRequires(name, type_name);
+ }
+
+ std::string RegisterRequires(const std::string &local_name,
+ const std::string &requires_name) {
+ requires_[local_name] = requires_name;
+ return local_name;
+ }
+
+ void EmitCodeBlock(const std::string &code_block, const std::string &name,
+ const std::string &ns,
+ const std::string &declaring_file) const {
+ const std::string root_type = schema_->root_table()->name()->str();
+ const std::string root_file =
+ schema_->root_table()->declaration_file()->str();
+ const std::string full_qualified_name = ns.empty() ? name : ns + "." + name;
+
+ std::string code = "--[[ " + full_qualified_name + "\n\n";
+ code +=
+ " Automatically generated by the FlatBuffers compiler, do not "
+ "modify.\n";
+ code += " Or modify. I'm a message, not a cop.\n";
+ code += "\n";
+ code += " flatc version: " + flatc_version_ + "\n";
+ code += "\n";
+ code += " Declared by : " + declaring_file + "\n";
+ code += " Rooting type : " + root_type + " (" + root_file + ")\n";
+ code += "\n--]]\n\n";
+
+ if (!requires_.empty()) {
+ for (auto it = requires_.cbegin(); it != requires_.cend(); ++it) {
+ code += "local " + it->first + " = require('" + it->second + "')\n";
+ }
+ code += "\n";
+ }
+
+ code += code_block;
+ code += "return " + name;
+
+ // Namespaces are '.' deliminted, so replace it with the path separator.
+ std::string path = ns;
+
+ if (ns.empty()) {
+ path = ".";
+ } else {
+ std::replace(path.begin(), path.end(), '.', '/');
+ }
+
+ // TODO(derekbailey): figure out a save file without depending on util.h
+ EnsureDirExists(path);
+ const std::string file_name = path + "/" + namer_.File(name);
+ SaveFile(file_name.c_str(), code, false);
+ }
+
+ std::unordered_set<std::string> keywords_;
+ std::map<std::string, std::string> requires_;
+ const r::Object *current_obj_;
+ const r::Enum *current_enum_;
+ const std::string flatc_version_;
+ const BfbsNamer namer_;
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewLuaBfbsGenerator(
+ const std::string &flatc_version) {
+ return std::unique_ptr<LuaBfbsGenerator>(new LuaBfbsGenerator(flatc_version));
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/bfbs_gen_lua.h b/contrib/libs/flatbuffers/src/bfbs_gen_lua.h
new file mode 100644
index 0000000000..86d97621eb
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_gen_lua.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 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_BFBS_GEN_LUA_H_
+#define FLATBUFFERS_BFBS_GEN_LUA_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Lua Code generator.
+std::unique_ptr<CodeGenerator> NewLuaBfbsGenerator(
+ const std::string &flatc_version);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_GEN_LUA_H_
diff --git a/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp b/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
new file mode 100644
index 0000000000..45bd3c33d4
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp
@@ -0,0 +1,692 @@
+/*
+ * Copyright 2021 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 "bfbs_gen_nim.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+// Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
+#include "bfbs_gen.h"
+#include "bfbs_namer.h"
+
+// The intermediate representation schema.
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/reflection_generated.h"
+
+namespace flatbuffers {
+namespace {
+
+// To reduce typing
+namespace r = ::reflection;
+
+std::set<std::string> NimKeywords() {
+ return {
+ "addr", "and", "as", "asm", "bind", "block",
+ "break", "case", "cast", "concept", "const", "continue",
+ "converter", "defer", "discard", "distinct", "div", "do",
+ "elif", "else", "end", "enum", "except", "export",
+ "finally", "for", "from", "func", "if", "import",
+ "in", "include", "interface", "is", "isnot", "iterator",
+ "let", "macro", "method", "mixin", "mod", "nil",
+ "not", "notin", "object", "of", "or", "out",
+ "proc", "ptr", "raise", "ref", "return", "shl",
+ "shr", "static", "template", "try", "tuple", "type",
+ "using", "var", "when", "while", "xor", "yield",
+ };
+}
+
+Namer::Config NimDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kUpperCamel,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variable=*/Case::kLowerCamel,
+ /*variants=*/Case::kUpperCamel,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"/",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".nim" };
+}
+
+const std::string Indent = " ";
+const std::string Export = "*";
+const std::set<std::string> builtin_types = {
+ "uint8", "uint8", "bool", "int8", "uint8", "int16",
+ "uint16", "int32", "uint32", "int64", "uint64", "float32",
+ "float64", "string", "int", "uint", "uoffset", "Builder"
+};
+
+class NimBfbsGenerator : public BaseBfbsGenerator {
+ public:
+ explicit NimBfbsGenerator(const std::string &flatc_version)
+ : BaseBfbsGenerator(),
+ keywords_(),
+ imports_(),
+ current_obj_(nullptr),
+ current_enum_(nullptr),
+ flatc_version_(flatc_version),
+ namer_(NimDefaultConfig(), NimKeywords()) {}
+
+ Status GenerateFromSchema(const r::Schema *schema) FLATBUFFERS_OVERRIDE {
+ ForAllEnums(schema->enums(), [&](const r::Enum *enum_def) {
+ StartCodeBlock(enum_def);
+ GenerateEnum(enum_def);
+ });
+ ForAllObjects(schema->objects(), [&](const r::Object *object) {
+ StartCodeBlock(object);
+ GenerateObject(object);
+ });
+ return OK;
+ }
+
+ using BaseBfbsGenerator::GenerateCode;
+
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return true; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kNim; }
+
+ std::string LanguageName() const override { return "Nim"; }
+
+ uint64_t SupportedAdvancedFeatures() const FLATBUFFERS_OVERRIDE {
+ return r::AdvancedArrayFeatures | r::AdvancedUnionFeatures |
+ r::OptionalScalars | r::DefaultVectorsAndStrings;
+ }
+
+ protected:
+ void GenerateEnum(const r::Enum *enum_def) {
+ std::string code;
+
+ std::string ns;
+ const std::string enum_name = namer_.Type(namer_.Denamespace(enum_def, ns));
+ const std::string enum_type =
+ GenerateTypeBasic(enum_def->underlying_type());
+
+ GenerateDocumentation(enum_def->documentation(), "", code);
+ code += "type " + enum_name + Export + "{.pure.} = enum\n";
+
+ ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
+ GenerateDocumentation(enum_val->documentation(), " ", code);
+ code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
+ NumToString(enum_val->value()) + "." + enum_type + ",\n";
+ });
+
+ EmitCodeBlock(code, enum_name, ns, enum_def->declaration_file()->str());
+ }
+
+ void GenerateObject(const r::Object *object) {
+ // Register the main flatbuffers module.
+ RegisterImports("flatbuffers", "");
+ std::string code;
+
+ std::string ns;
+ const std::string object_name = namer_.Type(namer_.Denamespace(object, ns));
+
+ GenerateDocumentation(object->documentation(), "", code);
+ code += "type " + object_name + "* = object of FlatObj\n";
+
+ // Create all the field accessors.
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ // Skip writing deprecated fields altogether.
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const r::BaseType base_type = field->type()->base_type();
+ std::string field_type = GenerateType(field->type());
+
+ if (field->optional() && !object->is_struct()) {
+ RegisterImports("std/options", "");
+ field_type = "Option[" + field_type + "]";
+ }
+
+ const std::string offset_prefix =
+ "let o = self.tab.Offset(" + NumToString(field->offset()) + ")\n";
+ const std::string offset_prefix_2 = "if o != 0:\n";
+
+ if (IsScalar(base_type) || base_type == r::String ||
+ base_type == r::Obj || base_type == r::Union) {
+ GenerateDocumentation(field->documentation(), "", code);
+
+ std::string getter_signature = "func " + namer_.Method(field_name) +
+ "*(self: " + object_name +
+ "): " + field_type + " =\n";
+ std::string getter_code;
+ std::string setter_signature =
+ "func `" + namer_.Method(field_name + "=") + "`*(self: var " +
+ object_name + ", n: " + field_type + "): bool =\n";
+ std::string setter_code;
+
+ if (base_type == r::Obj || base_type == r::Union ||
+ field->type()->index() >= 0) {
+ RegisterImports(object, field);
+ }
+
+ if (object->is_struct()) {
+ std::string field_getter =
+ GenerateGetter(field->type(), NumToString(field->offset()));
+ getter_code += " return " + field_getter + "\n";
+
+ if (IsScalar(base_type)) {
+ setter_code += " return self.tab.Mutate(self.tab.Pos + " +
+ NumToString(field->offset()) + ", n)\n";
+ }
+ } else {
+ // Table accessors
+ getter_code += " " + offset_prefix;
+ getter_code += " " + offset_prefix_2;
+ std::string field_getter = GenerateGetter(field->type(), "o");
+ if (field->optional()) {
+ field_getter = "some(" + field_getter + ")";
+ }
+ getter_code += " return " + field_getter + "\n";
+ if (!field->optional()) {
+ getter_code += " return " + DefaultValue(field) + "\n";
+ }
+
+ if (IsScalar(base_type)) {
+ setter_code += " return self.tab.MutateSlot(" +
+ NumToString(field->offset()) + ", n)\n";
+ }
+ }
+ code += getter_signature + getter_code;
+ if (IsScalar(base_type)) { code += setter_signature + setter_code; }
+ } else if (base_type == r::Array || base_type == r::Vector) {
+ const r::BaseType vector_base_type = field->type()->element();
+ uint32_t element_size = field->type()->element_size();
+
+ if (vector_base_type == r::Obj || vector_base_type == r::Union ||
+ field->type()->index() >= 0) {
+ RegisterImports(object, field, true);
+ }
+
+ // Get vector length:
+ code += "func " + namer_.Method(field_name + "Length") +
+ "*(self: " + object_name + "): int = \n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " return self.tab.VectorLen(o)\n";
+
+ // Get single vector field:
+ code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
+ ", j: int): " + GenerateType(field->type(), true) + " = \n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " var x = self.tab.Vector(o)\n";
+ code +=
+ " x += j.uoffset * " + NumToString(element_size) + ".uoffset\n";
+ code += " return " + GenerateGetter(field->type(), "x", true) + "\n";
+
+ // Get entire vector:
+ code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
+ "): " + GenerateType(field->type()) + " = \n";
+ code += " let len = self." + field_name + "Length\n";
+ code += " for i in countup(0, len - 1):\n";
+ code += " result.add(self." + field_name + "(i))\n";
+
+ (void)IsSingleByte(vector_base_type); // unnused function warning
+ }
+ });
+
+ // Create all the builders
+ if (object->is_struct()) {
+ code += "proc " + namer_.Function(object_name + "Create") +
+ "*(self: var Builder";
+ code += GenerateStructBuilderArgs(object);
+ code += "): uoffset =\n";
+ code += AppendStructBuilderBody(object);
+ code += " return self.Offset()\n";
+ } else {
+ // Table builders
+ code += "proc " + namer_.Function(object_name + "Start") +
+ "*(builder: var Builder) =\n";
+ code += " builder.StartObject(" + NumToString(object->fields()->size()) +
+ ")\n";
+
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const std::string variable_name = namer_.Variable(*field);
+ const std::string variable_type = GenerateTypeBasic(field->type());
+
+ code += "proc " + namer_.Function(object_name + "Add" + field_name) +
+ "*(builder: var Builder, " + variable_name + ": " +
+ variable_type + ") =\n";
+ code += " builder.Prepend" + GenerateMethod(field) + "Slot(" +
+ NumToString(field->id()) + ", " + variable_name + ", default(" +
+ variable_type + "))\n";
+
+ if (IsVector(field->type()->base_type())) {
+ code += "proc " +
+ namer_.Function(object_name + "Start" + field_name) +
+ "Vector*(builder: var Builder, numElems: uoffset) =\n";
+
+ const int32_t element_size = field->type()->element_size();
+ int32_t alignment = element_size;
+ if (IsStruct(field->type(), /*use_element=*/true)) {
+ alignment = GetObjectByIndex(field->type()->index())->minalign();
+ }
+
+ code += " builder.StartVector(" + NumToString(element_size) +
+ ", numElems, " + NumToString(alignment) + ")\n";
+ }
+ });
+
+ code += "proc " + namer_.Function(object_name + "End") +
+ "*(builder: var Builder): uoffset =\n";
+ code += " return builder.EndObject()\n";
+ }
+ EmitCodeBlock(code, object_name, ns, object->declaration_file()->str());
+ }
+
+ private:
+ void GenerateDocumentation(
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
+ *documentation,
+ std::string indent, std::string &code) const {
+ flatbuffers::ForAllDocumentation(
+ documentation, [&](const flatbuffers::String *str) {
+ code += indent + "# " + str->str() + "\n";
+ });
+ }
+
+ std::string GenerateStructBuilderArgs(const r::Object *object,
+ std::string prefix = "") const {
+ std::string signature;
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ signature += GenerateStructBuilderArgs(
+ field_object, prefix + namer_.Variable(*field) + "_");
+ } else {
+ signature += ", " + prefix + namer_.Variable(*field) + ": " +
+ GenerateType(field->type());
+ }
+ });
+ return signature;
+ }
+
+ std::string AppendStructBuilderBody(const r::Object *object,
+ std::string prefix = "") const {
+ std::string code;
+ code += " self.Prep(" + NumToString(object->minalign()) + ", " +
+ NumToString(object->bytesize()) + ")\n";
+
+ // We need to reverse the order we iterate over, since we build the
+ // buffer backwards.
+ ForAllFields(object, /*reverse=*/true, [&](const r::Field *field) {
+ const int32_t num_padding_bytes = field->padding();
+ if (num_padding_bytes) {
+ code += " self.Pad(" + NumToString(num_padding_bytes) + ")\n";
+ }
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ code += AppendStructBuilderBody(field_object,
+ prefix + namer_.Variable(*field) + "_");
+ } else {
+ code += " self.Prepend(" + prefix + namer_.Variable(*field) + ")\n";
+ }
+ });
+
+ return code;
+ }
+
+ std::string GenerateMethod(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsStructOrTable(base_type)) { return "Struct"; }
+ return "";
+ }
+
+ std::string GenerateGetter(const r::Type *type, const std::string &offsetval,
+ bool element_type = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ std::string offset = offsetval;
+ if (!element_type) { offset = "self.tab.Pos + " + offset; }
+ switch (base_type) {
+ case r::String: return "self.tab.String(" + offset + ")";
+ case r::Union: return "self.tab.Union(" + offsetval + ")";
+ case r::Obj: {
+ return GenerateType(type, element_type) +
+ "(tab: Vtable(Bytes: self.tab.Bytes, Pos: " + offset + "))";
+ }
+ case r::Vector: return GenerateGetter(type, offsetval, true);
+ default:
+ const r::Enum *type_enum = GetEnum(type, element_type);
+ if (type_enum != nullptr) {
+ return GenerateType(type, element_type) + "(" + "Get[" +
+ GenerateType(base_type) + "](self.tab, " + offset + ")" + ")";
+ } else {
+ return "Get[" + GenerateType(base_type) + "](self.tab, " + offset +
+ ")";
+ }
+ }
+ }
+
+ std::string Denamespace(const std::string &s, std::string &importns,
+ std::string &ns) const {
+ if (builtin_types.find(s) != builtin_types.end()) { return s; }
+ std::string type = namer_.Type(namer_.Denamespace(s, ns));
+ importns = ns.empty() ? type : ns + "." + type;
+ std::replace(importns.begin(), importns.end(), '.', '_');
+ return type;
+ }
+
+ std::string Denamespace(const std::string &s, std::string &importns) const {
+ std::string ns;
+ return Denamespace(s, importns, ns);
+ }
+
+ std::string Denamespace(const std::string &s) const {
+ std::string importns;
+ return Denamespace(s, importns);
+ }
+
+ std::string GenerateType(const r::Type *type, bool element_type = false,
+ bool enum_inner = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (IsScalar(base_type) && !enum_inner) {
+ const r::Enum *type_enum = GetEnum(type, element_type);
+ if (type_enum != nullptr) {
+ std::string importns;
+ std::string type_name = Denamespace(type_enum->name()->str(), importns);
+ return importns + "." + type_name;
+ }
+ }
+ if (IsScalar(base_type)) { return Denamespace(GenerateType(base_type)); }
+ switch (base_type) {
+ case r::String: return "string";
+ case r::Vector: {
+ return "seq[" + GenerateType(type, true) + "]";
+ }
+ case r::Union: return "Vtable";
+ case r::Obj: {
+ const r::Object *type_obj = GetObject(type, element_type);
+ std::string importns;
+ std::string type_name = Denamespace(type_obj->name()->str(), importns);
+ if (type_obj == current_obj_) {
+ return type_name;
+ } else {
+ return importns + "." + type_name;
+ }
+ }
+ default: return "uoffset";
+ }
+ }
+
+ std::string GenerateTypeBasic(const r::Type *type,
+ bool element_type = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (IsScalar(base_type)) {
+ return GenerateType(base_type);
+ } else {
+ return "uoffset";
+ }
+ }
+
+ std::string GenerateType(const r::BaseType base_type) const {
+ switch (base_type) {
+ case r::None: return "uint8";
+ case r::UType: return "uint8";
+ case r::Bool: return "bool";
+ case r::Byte: return "int8";
+ case r::UByte: return "uint8";
+ case r::Short: return "int16";
+ case r::UShort: return "uint16";
+ case r::Int: return "int32";
+ case r::UInt: return "uint32";
+ case r::Long: return "int64";
+ case r::ULong: return "uint64";
+ case r::Float: return "float32";
+ case r::Double: return "float64";
+ case r::String: return "string";
+ default: return r::EnumNameBaseType(base_type);
+ }
+ }
+
+ std::string DefaultValue(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsFloatingPoint(base_type)) {
+ if (field->default_real() != field->default_real()) {
+ return "NaN";
+ } else if (field->default_real() ==
+ std::numeric_limits<double>::infinity()) {
+ return "Inf";
+ } else if (field->default_real() ==
+ -std::numeric_limits<double>::infinity()) {
+ return "-Inf";
+ }
+ return NumToString(field->default_real());
+ }
+ if (IsBool(base_type)) {
+ return field->default_integer() ? "true" : "false";
+ }
+ if (IsScalar(base_type)) {
+ const r::Enum *type_enum = GetEnum(field->type());
+ if (type_enum != nullptr) {
+ return "type(result)(" + NumToString((field->default_integer())) + ")";
+ }
+ return NumToString((field->default_integer()));
+ }
+ if (base_type == r::String) { return "\"\""; }
+ // represents offsets
+ return "0";
+ }
+
+ void StartCodeBlock(const reflection::Enum *enum_def) {
+ current_enum_ = enum_def;
+ current_obj_ = nullptr;
+ imports_.clear();
+ }
+
+ void StartCodeBlock(const reflection::Object *object) {
+ current_enum_ = nullptr;
+ current_obj_ = object;
+ imports_.clear();
+ }
+
+ std::vector<std::string> StringSplit(const std::string orig_str,
+ const std::string token) {
+ std::vector<std::string> result;
+ std::string str = orig_str;
+ while (str.size()) {
+ size_t index = str.find(token);
+ if (index != std::string::npos) {
+ result.push_back(str.substr(0, index));
+ str = str.substr(index + token.size());
+ if (str.size() == 0) result.push_back(str);
+ } else {
+ result.push_back(str);
+ str = "";
+ }
+ }
+ return result;
+ }
+
+ std::string GetRelativePathFromNamespace(const std::string &relative_to,
+ const std::string &str2) {
+ std::vector<std::string> relative_to_vec = StringSplit(relative_to, ".");
+ std::vector<std::string> str2_vec = StringSplit(str2, ".");
+ while (relative_to_vec.size() > 0 && str2_vec.size() > 0) {
+ if (relative_to_vec[0] == str2_vec[0]) {
+ relative_to_vec.erase(relative_to_vec.begin());
+ str2_vec.erase(str2_vec.begin());
+ } else {
+ break;
+ }
+ }
+ relative_to_vec.pop_back();
+ for (size_t i = 0; i < relative_to_vec.size(); ++i) {
+ str2_vec.insert(str2_vec.begin(), std::string(".."));
+ }
+
+ std::string new_path;
+ for (size_t i = 0; i < str2_vec.size(); ++i) {
+ new_path += str2_vec[i];
+ if (i != str2_vec.size() - 1) { new_path += "/"; }
+ }
+ return new_path;
+ }
+
+ void RegisterImports(const r::Object *object, const r::Field *field,
+ bool use_element = false) {
+ std::string importns;
+ std::string type_name;
+
+ const r::BaseType type =
+ use_element ? field->type()->element() : field->type()->base_type();
+
+ if (IsStructOrTable(type)) {
+ const r::Object *object_def = GetObjectByIndex(field->type()->index());
+ if (object_def == current_obj_) { return; }
+ std::string ns;
+ type_name = Denamespace(object_def->name()->str(), importns, ns);
+ type_name = ns.empty() ? type_name : ns + "." + type_name;
+ } else {
+ const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
+ if (enum_def == current_enum_) { return; }
+ std::string ns;
+ type_name = Denamespace(enum_def->name()->str(), importns, ns);
+ type_name = ns.empty() ? type_name : ns + "." + type_name;
+ }
+
+ std::string import_path =
+ GetRelativePathFromNamespace(object->name()->str(), type_name);
+ std::replace(type_name.begin(), type_name.end(), '.', '_');
+ RegisterImports(import_path, importns);
+ }
+
+ void RegisterImports(const std::string &local_name,
+ const std::string &imports_name) {
+ imports_[local_name] = imports_name;
+ }
+
+ void EmitCodeBlock(const std::string &code_block, const std::string &name,
+ const std::string &ns, const std::string &declaring_file) {
+ const std::string full_qualified_name = ns.empty() ? name : ns + "." + name;
+
+ std::string code = "#[ " + full_qualified_name + "\n";
+ code +=
+ " Automatically generated by the FlatBuffers compiler, do not "
+ "modify.\n";
+ code += " Or modify. I'm a message, not a cop.\n";
+ code += "\n";
+ code += " flatc version: " + flatc_version_ + "\n";
+ code += "\n";
+ code += " Declared by : " + declaring_file + "\n";
+ if (schema_->root_table() != nullptr) {
+ const std::string root_type = schema_->root_table()->name()->str();
+ const std::string root_file =
+ schema_->root_table()->declaration_file()->str();
+ code += " Rooting type : " + root_type + " (" + root_file + ")\n";
+ }
+ code += "]#\n\n";
+
+ if (!imports_.empty()) {
+ for (auto it = imports_.cbegin(); it != imports_.cend(); ++it) {
+ if (it->second.empty()) {
+ code += "import " + it->first + "\n";
+ } else {
+ code += "import " + it->first + " as " + it->second + "\n";
+ }
+ }
+ code += "\n";
+ }
+ code += code_block;
+
+ // Namespaces are '.' deliminted, so replace it with the path separator.
+ std::string path = ns;
+
+ if (ns.empty()) {
+ path = ".";
+ } else {
+ std::replace(path.begin(), path.end(), '.', '/');
+ }
+
+ // TODO(derekbailey): figure out a save file without depending on util.h
+ EnsureDirExists(path);
+ const std::string file_name = path + "/" + namer_.File(name);
+ SaveFile(file_name.c_str(), code, false);
+ }
+
+ std::unordered_set<std::string> keywords_;
+ std::map<std::string, std::string> imports_;
+ const r::Object *current_obj_;
+ const r::Enum *current_enum_;
+ const std::string flatc_version_;
+ const BfbsNamer namer_;
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewNimBfbsGenerator(
+ const std::string &flatc_version) {
+ return std::unique_ptr<NimBfbsGenerator>(new NimBfbsGenerator(flatc_version));
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/bfbs_gen_nim.h b/contrib/libs/flatbuffers/src/bfbs_gen_nim.h
new file mode 100644
index 0000000000..39e8b21808
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_gen_nim.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 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_BFBS_GEN_NIM_H_
+#define FLATBUFFERS_BFBS_GEN_NIM_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Nim Code generator.
+std::unique_ptr<CodeGenerator> NewNimBfbsGenerator(
+ const std::string &flatc_version);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_GEN_NIM_H_
diff --git a/contrib/libs/flatbuffers/src/bfbs_namer.h b/contrib/libs/flatbuffers/src/bfbs_namer.h
new file mode 100644
index 0000000000..d197574cf7
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/bfbs_namer.h
@@ -0,0 +1,51 @@
+#ifndef FLATBUFFERS_BFBS_NAMER
+#define FLATBUFFERS_BFBS_NAMER
+
+#include "flatbuffers/reflection.h"
+#include "namer.h"
+
+namespace flatbuffers {
+
+// Provides Namer capabilities to types defined in the flatbuffers reflection.
+class BfbsNamer : public Namer {
+ public:
+ explicit BfbsNamer(Config config, std::set<std::string> keywords)
+ : Namer(config, std::move(keywords)) {}
+
+ using Namer::Constant;
+ using Namer::Denamespace;
+ using Namer::Directories;
+ using Namer::Field;
+ using Namer::File;
+ using Namer::Function;
+ using Namer::Method;
+ using Namer::Namespace;
+ using Namer::NamespacedType;
+ using Namer::ObjectType;
+ using Namer::Type;
+ using Namer::Variable;
+ using Namer::Variant;
+
+ template<typename T>
+ std::string Denamespace(T t, std::string &namespace_prefix,
+ const char delimiter = '.') const {
+ return Namer::Denamespace(t->name()->c_str(), namespace_prefix, delimiter);
+ }
+
+ template<typename T>
+ std::string Denamespace(T t, const char delimiter = '.') const {
+ return Namer::Denamespace(t->name()->c_str(), delimiter);
+ }
+
+ virtual std::string Field(const ::reflection::Field &f) const {
+ return Field(f.name()->str());
+ }
+
+ virtual std::string Variable(const ::reflection::Field &f) const {
+ return Variable(f.name()->str());
+ }
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_NAMER
diff --git a/contrib/libs/flatbuffers/src/binary_annotator.cpp b/contrib/libs/flatbuffers/src/binary_annotator.cpp
new file mode 100644
index 0000000000..498a7bfc6a
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/binary_annotator.cpp
@@ -0,0 +1,1519 @@
+#include "binary_annotator.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/util.h"
+#include "flatbuffers/verifier.h"
+
+namespace flatbuffers {
+namespace {
+
+static bool BinaryRegionSort(const BinaryRegion &a, const BinaryRegion &b) {
+ return a.offset < b.offset;
+}
+
+static void SetError(BinaryRegionComment &comment, BinaryRegionStatus status,
+ std::string message = "") {
+ comment.status = status;
+ comment.status_message = message;
+}
+
+static BinaryRegion MakeBinaryRegion(
+ const uint64_t offset = 0, const uint64_t length = 0,
+ const BinaryRegionType type = BinaryRegionType::Unknown,
+ const uint64_t array_length = 0, const uint64_t points_to_offset = 0,
+ BinaryRegionComment comment = {}) {
+ BinaryRegion region;
+ region.offset = offset;
+ region.length = length;
+ region.type = type;
+ region.array_length = array_length;
+ region.points_to_offset = points_to_offset;
+ region.comment = std::move(comment);
+ return region;
+}
+
+static BinarySection MakeBinarySection(const std::string &name,
+ const BinarySectionType type,
+ std::vector<BinaryRegion> regions) {
+ BinarySection section;
+ section.name = name;
+ section.type = type;
+ section.regions = std::move(regions);
+ return section;
+}
+
+static BinarySection MakeSingleRegionBinarySection(const std::string &name,
+ const BinarySectionType type,
+ const BinaryRegion &region) {
+ std::vector<BinaryRegion> regions;
+ regions.push_back(region);
+ return MakeBinarySection(name, type, std::move(regions));
+}
+
+static bool IsNonZeroRegion(const uint64_t offset, const uint64_t length,
+ const uint8_t *const binary) {
+ for (uint64_t i = offset; i < offset + length; ++i) {
+ if (binary[i] != 0) { return true; }
+ }
+ return false;
+}
+
+static bool IsPrintableRegion(const uint64_t offset, const uint64_t length,
+ const uint8_t *const binary) {
+ for (uint64_t i = offset; i < offset + length; ++i) {
+ if (!isprint(binary[i])) { return false; }
+ }
+ return true;
+}
+
+static BinarySection GenerateMissingSection(const uint64_t offset,
+ const uint64_t length,
+ const uint8_t *const binary) {
+ std::vector<BinaryRegion> regions;
+
+ // Check if the region is all zeros or not, as that can tell us if it is
+ // padding or not.
+ if (IsNonZeroRegion(offset, length, binary)) {
+ // Some of the padding bytes are non-zero, so this might be an unknown
+ // section of the binary.
+ // TODO(dbaileychess): We could be a bit smarter with different sized
+ // alignments. For now, the 8 byte check encompasses all the smaller
+ // alignments.
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Unknown;
+ if (length >= 8) {
+ SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+ } else {
+ SetError(comment, BinaryRegionStatus::WARN_CORRUPTED_PADDING);
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+ BinaryRegionType::Unknown, length, 0,
+ comment));
+
+ return MakeBinarySection("no known references", BinarySectionType::Unknown,
+ std::move(regions));
+ }
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Padding;
+ if (length >= 8) {
+ SetError(comment, BinaryRegionStatus::WARN_PADDING_LENGTH);
+ }
+
+ // This region is most likely padding.
+ regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+ BinaryRegionType::Uint8, length, 0,
+ comment));
+
+ return MakeBinarySection("", BinarySectionType::Padding, std::move(regions));
+}
+
+} // namespace
+
+std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
+ flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
+
+ if ((is_size_prefixed_ &&
+ !reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
+ !reflection::VerifySchemaBuffer(verifier)) {
+ return {};
+ }
+
+ // The binary is too short to read as a flatbuffers.
+ if (binary_length_ < FLATBUFFERS_MIN_BUFFER_SIZE) { return {}; }
+
+ // Make sure we start with a clean slate.
+ vtables_.clear();
+ sections_.clear();
+
+ // First parse the header region which always start at offset 0.
+ // The returned offset will point to the root_table location.
+ const uint64_t root_table_offset = BuildHeader(0);
+
+ if (IsValidOffset(root_table_offset)) {
+ // Build the root table, and all else will be referenced from it.
+ BuildTable(root_table_offset, BinarySectionType::RootTable,
+ schema_->root_table());
+ }
+
+ // Now that all the sections are built, make sure the binary sections are
+ // contiguous.
+ FixMissingRegions();
+
+ // Then scan the area between BinarySections insert padding sections that are
+ // implied.
+ FixMissingSections();
+
+ return sections_;
+}
+
+uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
+ uint64_t offset = header_offset;
+ std::vector<BinaryRegion> regions;
+
+ // If this binary is a size prefixed one, attempt to parse the size.
+ if (is_size_prefixed_) {
+ BinaryRegionComment prefix_length_comment;
+ prefix_length_comment.type = BinaryRegionCommentType::SizePrefix;
+
+ bool has_prefix_value = false;
+ const auto prefix_length = ReadScalar<uoffset64_t>(offset);
+ if (*prefix_length <= binary_length_) {
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset64_t),
+ BinaryRegionType::Uint64, 0, 0,
+ prefix_length_comment));
+ offset += sizeof(uoffset64_t);
+ has_prefix_value = true;
+ }
+
+ if (!has_prefix_value) {
+ const auto prefix_length = ReadScalar<uoffset_t>(offset);
+ if (*prefix_length <= binary_length_) {
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset_t),
+ BinaryRegionType::Uint32, 0, 0,
+ prefix_length_comment));
+ offset += sizeof(uoffset_t);
+ has_prefix_value = true;
+ }
+ }
+
+ if (!has_prefix_value) {
+ SetError(prefix_length_comment, BinaryRegionStatus::ERROR);
+ }
+ }
+
+ const auto root_table_offset = ReadScalar<uint32_t>(offset);
+
+ if (!root_table_offset.has_value()) {
+ // This shouldn't occur, since we validate the min size of the buffer
+ // before. But for completion sake, we shouldn't read passed the binary end.
+ return std::numeric_limits<uint64_t>::max();
+ }
+
+ const auto root_table_loc = offset + *root_table_offset;
+
+ BinaryRegionComment root_offset_comment;
+ root_offset_comment.type = BinaryRegionCommentType::RootTableOffset;
+ root_offset_comment.name = schema_->root_table()->name()->str();
+
+ if (!IsValidOffset(root_table_loc)) {
+ SetError(root_offset_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ root_table_loc, root_offset_comment));
+ offset += sizeof(uint32_t);
+
+ if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
+ IsPrintableRegion(offset, flatbuffers::kFileIdentifierLength, binary_)) {
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::FileIdentifier;
+ // Check if the file identifier region has non-zero data, and assume its
+ // the file identifier. Otherwise, it will get filled in with padding
+ // later.
+ regions.push_back(MakeBinaryRegion(
+ offset, flatbuffers::kFileIdentifierLength * sizeof(uint8_t),
+ BinaryRegionType::Char, flatbuffers::kFileIdentifierLength, 0,
+ comment));
+ }
+
+ AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
+ std::move(regions)));
+
+ return root_table_loc;
+}
+
+BinaryAnnotator::VTable *BinaryAnnotator::GetOrBuildVTable(
+ const uint64_t vtable_offset, const reflection::Object *const table,
+ const uint64_t offset_of_referring_table) {
+ // Get a list of vtables (if any) already defined at this offset.
+ std::list<VTable> &vtables = vtables_[vtable_offset];
+
+ // See if this vtable for the table type has been generated before.
+ for (VTable &vtable : vtables) {
+ if (vtable.referring_table == table) { return &vtable; }
+ }
+
+ // If we are trying to make a new vtable and it is already encompassed by
+ // another binary section, something is corrupted.
+ if (vtables.empty() && ContainsSection(vtable_offset)) { return nullptr; }
+
+ const std::string referring_table_name = table->name()->str();
+
+ BinaryRegionComment vtable_size_comment;
+ vtable_size_comment.type = BinaryRegionCommentType::VTableSize;
+
+ const auto vtable_length = ReadScalar<uint16_t>(vtable_offset);
+ if (!vtable_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(vtable_offset);
+
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "2");
+
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ referring_table_name, BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ vtable_size_comment)));
+ return nullptr;
+ }
+
+ // Vtables start with the size of the vtable
+ const uint16_t vtable_size = vtable_length.value();
+
+ if (!IsValidOffset(vtable_offset + vtable_size - 1)) {
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ // The vtable_size points to off the end of the binary.
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ referring_table_name, BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment)));
+
+ return nullptr;
+ } else if (vtable_size < 2 * sizeof(uint16_t)) {
+ SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+ "4");
+ // The size includes itself and the table size which are both uint16_t.
+ AddSection(vtable_offset,
+ MakeSingleRegionBinarySection(
+ referring_table_name, BinarySectionType::VTable,
+ MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment)));
+ return nullptr;
+ }
+
+ std::vector<BinaryRegion> regions;
+
+ regions.push_back(MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ vtable_size_comment));
+ uint64_t offset = vtable_offset + sizeof(uint16_t);
+
+ BinaryRegionComment ref_table_len_comment;
+ ref_table_len_comment.type =
+ BinaryRegionCommentType::VTableRefferingTableLength;
+
+ // Ensure we can read the next uint16_t field, which is the size of the
+ // referring table.
+ const auto table_length = ReadScalar<uint16_t>(offset);
+
+ if (!table_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "2");
+
+ AddSection(offset, MakeSingleRegionBinarySection(
+ referring_table_name, BinarySectionType::VTable,
+ MakeBinaryRegion(
+ offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, ref_table_len_comment)));
+ return nullptr;
+ }
+
+ // Then they have the size of the table they reference.
+ const uint16_t table_size = table_length.value();
+
+ if (!IsValidOffset(offset_of_referring_table + table_size - 1)) {
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ } else if (table_size < 4) {
+ SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+ "4");
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint16_t),
+ BinaryRegionType::Uint16, 0, 0,
+ ref_table_len_comment));
+ offset += sizeof(uint16_t);
+
+ const uint64_t offset_start = offset;
+
+ // A mapping between field (and its id) to the relative offset (uin16_t) from
+ // the start of the table.
+ std::map<uint16_t, VTable::Entry> fields;
+
+ // Counter for determining if the binary has more vtable entries than the
+ // schema provided. This can occur if the binary was created at a newer schema
+ // version and is being processed with an older one.
+ uint16_t fields_processed = 0;
+
+ // Loop over all the fields.
+ ForAllFields(table, /*reverse=*/false, [&](const reflection::Field *field) {
+ const uint64_t field_offset = offset_start + field->id() * sizeof(uint16_t);
+
+ if (field_offset >= vtable_offset + vtable_size) {
+ // This field_offset is too large for this vtable, so it must come from a
+ // newer schema than the binary was create with or the binary writer did
+ // not write it. For either case, it is safe to ignore.
+
+ // TODO(dbaileychess): We could show which fields are not set an their
+ // default values if we want. We just need a way to make it obvious that
+ // it isn't part of the buffer.
+ return;
+ }
+
+ BinaryRegionComment field_comment;
+ field_comment.type = BinaryRegionCommentType::VTableFieldOffset;
+ field_comment.name = std::string(field->name()->c_str()) +
+ "` (id: " + std::to_string(field->id()) + ")";
+
+ const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+ if (!offset_from_table.has_value()) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, field_comment));
+
+ return;
+ }
+
+ if (!IsValidOffset(offset_of_referring_table + offset_from_table.value() -
+ 1)) {
+ SetError(field_comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ return;
+ }
+
+ VTable::Entry entry;
+ entry.field = field;
+ entry.offset_from_table = offset_from_table.value();
+ fields.insert(std::make_pair(field->id(), entry));
+
+ std::string default_label;
+ if (offset_from_table.value() == 0) {
+ // Not present, so could be default or be optional.
+ if (field->required()) {
+ SetError(field_comment,
+ BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT);
+ // If this is a required field, make it known this is an error.
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ return;
+ } else {
+ // Its an optional field, so get the default value and interpret and
+ // provided an annotation for it.
+ if (IsScalar(field->type()->base_type())) {
+ default_label += "<defaults to ";
+ default_label += IsFloat(field->type()->base_type())
+ ? std::to_string(field->default_real())
+ : std::to_string(field->default_integer());
+ default_label += "> (";
+ } else {
+ default_label += "<null> (";
+ }
+ default_label +=
+ reflection::EnumNameBaseType(field->type()->base_type());
+ default_label += ")";
+ }
+ }
+ field_comment.default_value = default_label;
+
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+
+ fields_processed++;
+ });
+
+ // Check if we covered all the expectant fields. If not, we need to add them
+ // as unknown fields.
+ uint16_t expectant_vtable_fields =
+ (vtable_size - sizeof(uint16_t) - sizeof(uint16_t)) / sizeof(uint16_t);
+
+ // Prevent a bad binary from declaring a really large vtable_size, that we can
+ // not independently verify.
+ expectant_vtable_fields = std::min(
+ static_cast<uint16_t>(fields_processed * 3), expectant_vtable_fields);
+
+ for (uint16_t id = fields_processed; id < expectant_vtable_fields; ++id) {
+ const uint64_t field_offset = offset_start + id * sizeof(uint16_t);
+
+ const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+ BinaryRegionComment field_comment;
+ field_comment.type = BinaryRegionCommentType::VTableUnknownFieldOffset;
+ field_comment.index = id;
+
+ if (!offset_from_table.has_value()) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+ SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, field_comment));
+ continue;
+ }
+
+ VTable::Entry entry;
+ entry.field = nullptr; // No field to reference.
+ entry.offset_from_table = offset_from_table.value();
+ fields.insert(std::make_pair(id, entry));
+
+ regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+ BinaryRegionType::VOffset, 0, 0,
+ field_comment));
+ }
+
+ // If we have never added this vtable before record the Binary section.
+ if (vtables.empty()) {
+ sections_[vtable_offset] = MakeBinarySection(
+ referring_table_name, BinarySectionType::VTable, std::move(regions));
+ } else {
+ // Add the current table name to the name of the section.
+ sections_[vtable_offset].name += ", " + referring_table_name;
+ }
+
+ VTable vtable;
+ vtable.referring_table = table;
+ vtable.fields = std::move(fields);
+ vtable.table_size = table_size;
+ vtable.vtable_size = vtable_size;
+
+ // Add this vtable to the collection of vtables at this offset.
+ vtables.push_back(std::move(vtable));
+
+ // Return the vtable we just added.
+ return &vtables.back();
+}
+
+void BinaryAnnotator::BuildTable(const uint64_t table_offset,
+ const BinarySectionType type,
+ const reflection::Object *const table) {
+ if (ContainsSection(table_offset)) { return; }
+
+ BinaryRegionComment vtable_offset_comment;
+ vtable_offset_comment.type = BinaryRegionCommentType::TableVTableOffset;
+
+ const auto vtable_soffset = ReadScalar<int32_t>(table_offset);
+
+ if (!vtable_soffset.has_value()) {
+ const uint64_t remaining = RemainingBytes(table_offset);
+ SetError(vtable_offset_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ AddSection(
+ table_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), type,
+ MakeBinaryRegion(table_offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vtable_offset_comment)));
+
+ // If there aren't enough bytes left to read the vtable offset, there is
+ // nothing we can do.
+ return;
+ }
+
+ // Tables start with the vtable
+ const uint64_t vtable_offset = table_offset - vtable_soffset.value();
+
+ if (!IsValidOffset(vtable_offset)) {
+ SetError(vtable_offset_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+ AddSection(table_offset,
+ MakeSingleRegionBinarySection(
+ table->name()->str(), type,
+ MakeBinaryRegion(table_offset, sizeof(int32_t),
+ BinaryRegionType::SOffset, 0, vtable_offset,
+ vtable_offset_comment)));
+
+ // There isn't much to do with an invalid vtable offset, as we won't be able
+ // to intepret the rest of the table fields.
+ return;
+ }
+
+ std::vector<BinaryRegion> regions;
+ regions.push_back(MakeBinaryRegion(table_offset, sizeof(int32_t),
+ BinaryRegionType::SOffset, 0,
+ vtable_offset, vtable_offset_comment));
+
+ // Parse the vtable first so we know what the rest of the fields in the table
+ // are.
+ const VTable *const vtable =
+ GetOrBuildVTable(vtable_offset, table, table_offset);
+
+ if (vtable == nullptr) {
+ // There is no valid vtable for this table, so we cannot process the rest of
+ // the table entries.
+ return;
+ }
+
+ // This is the size and length of this table.
+ const uint16_t table_size = vtable->table_size;
+ uint64_t table_end_offset = table_offset + table_size;
+
+ if (!IsValidOffset(table_end_offset - 1)) {
+ // We already validated the table size in BuildVTable, but we have to make
+ // sure we don't use a bad value here.
+ table_end_offset = binary_length_;
+ }
+
+ // We need to iterate over the vtable fields by their offset in the binary,
+ // not by their IDs. So copy them over to another vector that we can sort on
+ // the offset_from_table property.
+ std::vector<VTable::Entry> fields;
+ for (const auto &vtable_field : vtable->fields) {
+ fields.push_back(vtable_field.second);
+ }
+
+ std::stable_sort(fields.begin(), fields.end(),
+ [](const VTable::Entry &a, const VTable::Entry &b) {
+ return a.offset_from_table < b.offset_from_table;
+ });
+
+ // Iterate over all the fields by order of their offset.
+ for (size_t i = 0; i < fields.size(); ++i) {
+ const reflection::Field *field = fields[i].field;
+ const uint16_t offset_from_table = fields[i].offset_from_table;
+
+ if (offset_from_table == 0) {
+ // Skip non-present fields.
+ continue;
+ }
+
+ // The field offsets are relative to the start of the table.
+ const uint64_t field_offset = table_offset + offset_from_table;
+
+ if (!IsValidOffset(field_offset)) {
+ // The field offset is larger than the binary, nothing we can do.
+ continue;
+ }
+
+ // We have a vtable entry for a non-existant field, that means its a binary
+ // generated by a newer schema than we are currently processing.
+ if (field == nullptr) {
+ // Calculate the length of this unknown field.
+ const uint64_t unknown_field_length =
+ // Check if there is another unknown field after this one.
+ ((i + 1 < fields.size())
+ ? table_offset + fields[i + 1].offset_from_table
+ // Otherwise use the known end of the table.
+ : table_end_offset) -
+ field_offset;
+
+ if (unknown_field_length == 0) { continue; }
+
+ std::string hint;
+
+ if (unknown_field_length == 4) {
+ const auto relative_offset = ReadScalar<uint32_t>(field_offset);
+ if (relative_offset.has_value()) {
+ // The field is 4 in length, so it could be an offset? Provide a hint.
+ hint += "<possibly an offset? Check Loc: +0x";
+ hint += ToHex(field_offset + relative_offset.value());
+ hint += ">";
+ }
+ }
+
+ BinaryRegionComment unknown_field_comment;
+ unknown_field_comment.type = BinaryRegionCommentType::TableUnknownField;
+
+ if (!IsValidRead(field_offset, unknown_field_length)) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(unknown_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(unknown_field_length));
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, unknown_field_comment));
+ continue;
+ }
+
+ unknown_field_comment.default_value = hint;
+
+ regions.push_back(MakeBinaryRegion(
+ field_offset, unknown_field_length, BinaryRegionType::Unknown,
+ unknown_field_length, 0, unknown_field_comment));
+ continue;
+ }
+
+ if (IsScalar(field->type()->base_type())) {
+ // These are the raw values store in the table.
+ const uint64_t type_size = GetTypeSize(field->type()->base_type());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->base_type());
+
+ BinaryRegionComment scalar_field_comment;
+ scalar_field_comment.type = BinaryRegionCommentType::TableField;
+ scalar_field_comment.name =
+ std::string(field->name()->c_str()) + "` (" +
+ reflection::EnumNameBaseType(field->type()->base_type()) + ")";
+
+ if (!IsValidRead(field_offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+ SetError(scalar_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, scalar_field_comment));
+ continue;
+ }
+
+ if (IsUnionType(field)) {
+ // This is a type for a union. Validate the value
+ const auto enum_value = ReadScalar<uint8_t>(field_offset);
+
+ // This should always have a value, due to the IsValidRead check above.
+ if (!IsValidUnionValue(field, enum_value.value())) {
+ SetError(scalar_field_comment,
+ BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+
+ regions.push_back(MakeBinaryRegion(field_offset, type_size,
+ region_type, 0, 0,
+ scalar_field_comment));
+ continue;
+ }
+ }
+
+ regions.push_back(MakeBinaryRegion(field_offset, type_size, region_type,
+ 0, 0, scalar_field_comment));
+ continue;
+ }
+
+ // Read the offset
+ uint64_t offset = 0;
+ uint64_t length = sizeof(uint32_t);
+ BinaryRegionType region_type = BinaryRegionType::UOffset;
+
+ if (field->offset64()) {
+ length = sizeof(uint64_t);
+ region_type = BinaryRegionType::UOffset64;
+ offset = ReadScalar<uint64_t>(field_offset).value_or(0);
+ } else {
+ offset = ReadScalar<uint32_t>(field_offset).value_or(0);
+ }
+ // const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
+ uint64_t offset_of_next_item = 0;
+ BinaryRegionComment offset_field_comment;
+ offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
+ offset_field_comment.name = field->name()->c_str();
+ const std::string offset_prefix =
+ "offset to field `" + std::string(field->name()->c_str()) + "`";
+
+ // Validate any field that isn't inline (i.e., non-structs).
+ if (!IsInlineField(field)) {
+ if (offset == 0) {
+ const uint64_t remaining = RemainingBytes(field_offset);
+
+ SetError(offset_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(MakeBinaryRegion(field_offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, offset_field_comment));
+ continue;
+ }
+
+ offset_of_next_item = field_offset + offset;
+
+ if (!IsValidOffset(offset_of_next_item)) {
+ SetError(offset_field_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
+ offset_of_next_item,
+ offset_field_comment));
+ continue;
+ }
+ }
+
+ switch (field->type()->base_type()) {
+ case reflection::BaseType::Obj: {
+ const reflection::Object *next_object =
+ schema_->objects()->Get(field->type()->index());
+
+ if (next_object->is_struct()) {
+ // Structs are stored inline.
+ BuildStruct(field_offset, regions, field->name()->c_str(),
+ next_object);
+ } else {
+ offset_field_comment.default_value = "(table)";
+
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type,
+ 0, offset_of_next_item,
+ offset_field_comment));
+
+ BuildTable(offset_of_next_item, BinarySectionType::Table,
+ next_object);
+ }
+ } break;
+
+ case reflection::BaseType::String: {
+ offset_field_comment.default_value = "(string)";
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
+ offset_of_next_item,
+ offset_field_comment));
+ BuildString(offset_of_next_item, table, field);
+ } break;
+
+ case reflection::BaseType::Vector: {
+ offset_field_comment.default_value = "(vector)";
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
+ offset_of_next_item,
+ offset_field_comment));
+ BuildVector(offset_of_next_item, table, field, table_offset,
+ vtable->fields);
+ } break;
+ case reflection::BaseType::Vector64: {
+ offset_field_comment.default_value = "(vector64)";
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
+ offset_of_next_item,
+ offset_field_comment));
+ BuildVector(offset_of_next_item, table, field, table_offset,
+ vtable->fields);
+ } break;
+
+ case reflection::BaseType::Union: {
+ const uint64_t union_offset = offset_of_next_item;
+
+ // The union type field is always one less than the union itself.
+ const uint16_t union_type_id = field->id() - 1;
+
+ auto vtable_field = vtable->fields.find(union_type_id);
+ if (vtable_field == vtable->fields.end()) {
+ // TODO(dbaileychess): need to capture this error condition.
+ break;
+ }
+ offset_field_comment.default_value = "(union)";
+
+ const uint64_t type_offset =
+ table_offset + vtable_field->second.offset_from_table;
+
+ const auto realized_type = ReadScalar<uint8_t>(type_offset);
+ if (!realized_type.has_value()) {
+ const uint64_t remaining = RemainingBytes(type_offset);
+ SetError(offset_field_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+ regions.push_back(MakeBinaryRegion(
+ type_offset, remaining, BinaryRegionType::Unknown, remaining, 0,
+ offset_field_comment));
+ continue;
+ }
+
+ if (!IsValidUnionValue(field, realized_type.value())) {
+ // We already export an error in the union type field, so just skip
+ // building the union itself and it will default to an unreference
+ // Binary section.
+ continue;
+ }
+
+ const std::string enum_type =
+ BuildUnion(union_offset, realized_type.value(), field);
+
+ offset_field_comment.default_value =
+ "(union of type `" + enum_type + "`)";
+
+ regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
+ union_offset, offset_field_comment));
+
+ } break;
+
+ default: break;
+ }
+ }
+
+ // Handle the case where there is padding after the last known binary
+ // region. Calculate where we left off towards the expected end of the
+ // table.
+ const uint64_t i = regions.back().offset + regions.back().length + 1;
+
+ if (i < table_end_offset) {
+ const uint64_t pad_bytes = table_end_offset - i + 1;
+
+ BinaryRegionComment padding_comment;
+ padding_comment.type = BinaryRegionCommentType::Padding;
+
+ regions.push_back(MakeBinaryRegion(i - 1, pad_bytes * sizeof(uint8_t),
+ BinaryRegionType::Uint8, pad_bytes, 0,
+ padding_comment));
+ }
+
+ AddSection(table_offset,
+ MakeBinarySection(table->name()->str(), type, std::move(regions)));
+}
+
+uint64_t BinaryAnnotator::BuildStruct(const uint64_t struct_offset,
+ std::vector<BinaryRegion> &regions,
+ const std::string referring_field_name,
+ const reflection::Object *const object) {
+ if (!object->is_struct()) { return struct_offset; }
+ uint64_t offset = struct_offset;
+
+ // Loop over all the fields in increasing order
+ ForAllFields(object, /*reverse=*/false, [&](const reflection::Field *field) {
+ if (IsScalar(field->type()->base_type())) {
+ // Structure Field value
+ const uint64_t type_size = GetTypeSize(field->type()->base_type());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->base_type());
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::StructField;
+ comment.name = referring_field_name + "." + field->name()->str();
+ comment.default_value = "of '" + object->name()->str() + "' (" +
+ std::string(reflection::EnumNameBaseType(
+ field->type()->base_type())) +
+ ")";
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, comment));
+
+ // TODO(dbaileychess): Should I bail out here? This sets offset to the
+ // end of the binary. So all other reads in the loop should fail.
+ offset += remaining;
+ return;
+ }
+
+ regions.push_back(
+ MakeBinaryRegion(offset, type_size, region_type, 0, 0, comment));
+ offset += type_size;
+ } else if (field->type()->base_type() == reflection::BaseType::Obj) {
+ // Structs are stored inline, even when nested.
+ offset = BuildStruct(offset, regions,
+ referring_field_name + "." + field->name()->str(),
+ schema_->objects()->Get(field->type()->index()));
+ } else if (field->type()->base_type() == reflection::BaseType::Array) {
+ const bool is_scalar = IsScalar(field->type()->element());
+ const uint64_t type_size = GetTypeSize(field->type()->element());
+ const BinaryRegionType region_type =
+ GetRegionType(field->type()->element());
+
+ // Arrays are just repeated structures.
+ for (uint16_t i = 0; i < field->type()->fixed_length(); ++i) {
+ if (is_scalar) {
+ BinaryRegionComment array_comment;
+ array_comment.type = BinaryRegionCommentType::ArrayField;
+ array_comment.name =
+ referring_field_name + "." + field->name()->str();
+ array_comment.index = i;
+ array_comment.default_value =
+ "of '" + object->name()->str() + "' (" +
+ std::string(
+ reflection::EnumNameBaseType(field->type()->element())) +
+ ")";
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(array_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown,
+ remaining, 0, array_comment));
+
+ // TODO(dbaileychess): Should I bail out here? This sets offset to
+ // the end of the binary. So all other reads in the loop should
+ // fail.
+ offset += remaining;
+ break;
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, type_size, region_type, 0,
+ 0, array_comment));
+
+ offset += type_size;
+ } else {
+ // Array of Structs.
+ //
+ // TODO(dbaileychess): This works, but the comments on the fields lose
+ // some context. Need to figure a way how to plumb the nested arrays
+ // comments together that isn't too confusing.
+ offset =
+ BuildStruct(offset, regions,
+ referring_field_name + "." + field->name()->str(),
+ schema_->objects()->Get(field->type()->index()));
+ }
+ }
+ }
+
+ // Insert any padding after this field.
+ const uint16_t padding = field->padding();
+ if (padding > 0 && IsValidOffset(offset + padding)) {
+ BinaryRegionComment padding_comment;
+ padding_comment.type = BinaryRegionCommentType::Padding;
+
+ regions.push_back(MakeBinaryRegion(offset, padding,
+ BinaryRegionType::Uint8, padding, 0,
+ padding_comment));
+ offset += padding;
+ }
+ });
+
+ return offset;
+}
+
+void BinaryAnnotator::BuildString(const uint64_t string_offset,
+ const reflection::Object *const table,
+ const reflection::Field *const field) {
+ // Check if we have already generated this string section, and this is a
+ // shared string instance.
+ if (ContainsSection(string_offset)) { return; }
+
+ std::vector<BinaryRegion> regions;
+ const auto string_length = ReadScalar<uint32_t>(string_offset);
+
+ BinaryRegionComment string_length_comment;
+ string_length_comment.type = BinaryRegionCommentType::StringLength;
+
+ if (!string_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(string_offset);
+
+ SetError(string_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ regions.push_back(MakeBinaryRegion(string_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ string_length_comment));
+
+ } else {
+ const uint32_t string_size = string_length.value();
+ const uint64_t string_end =
+ string_offset + sizeof(uint32_t) + string_size + sizeof(char);
+
+ if (!IsValidOffset(string_end - 1)) {
+ SetError(string_length_comment,
+ BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+
+ regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+ BinaryRegionType::Uint32, 0, 0,
+ string_length_comment));
+ } else {
+ regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+ BinaryRegionType::Uint32, 0, 0,
+ string_length_comment));
+
+ BinaryRegionComment string_comment;
+ string_comment.type = BinaryRegionCommentType::StringValue;
+
+ regions.push_back(MakeBinaryRegion(string_offset + sizeof(uint32_t),
+ string_size, BinaryRegionType::Char,
+ string_size, 0, string_comment));
+
+ BinaryRegionComment string_terminator_comment;
+ string_terminator_comment.type =
+ BinaryRegionCommentType::StringTerminator;
+
+ regions.push_back(MakeBinaryRegion(
+ string_offset + sizeof(uint32_t) + string_size, sizeof(char),
+ BinaryRegionType::Char, 0, 0, string_terminator_comment));
+ }
+ }
+
+ AddSection(string_offset,
+ MakeBinarySection(std::string(table->name()->c_str()) + "." +
+ field->name()->c_str(),
+ BinarySectionType::String, std::move(regions)));
+}
+
+void BinaryAnnotator::BuildVector(
+ const uint64_t vector_offset, const reflection::Object *const table,
+ const reflection::Field *const field, const uint64_t parent_table_offset,
+ const std::map<uint16_t, VTable::Entry> vtable_fields) {
+ if (ContainsSection(vector_offset)) { return; }
+
+ BinaryRegionComment vector_length_comment;
+ vector_length_comment.type = BinaryRegionCommentType::VectorLength;
+
+ const bool is_64_bit_vector =
+ field->type()->base_type() == reflection::BaseType::Vector64;
+
+ flatbuffers::Optional<uint64_t> vector_length;
+ uint32_t vector_length_size_type = 0;
+ BinaryRegionType region_type = BinaryRegionType::Uint32;
+ BinarySectionType section_type = BinarySectionType::Vector;
+
+ if (is_64_bit_vector) {
+ auto v = ReadScalar<uint64_t>(vector_offset);
+ if (v.has_value()) { vector_length = v.value(); }
+ vector_length_size_type = sizeof(uint64_t);
+ region_type = BinaryRegionType::Uint64;
+ section_type = BinarySectionType::Vector64;
+ } else {
+ auto v = ReadScalar<uint32_t>(vector_offset);
+ if (v.has_value()) { vector_length = v.value(); }
+ vector_length_size_type = sizeof(uint32_t);
+ region_type = BinaryRegionType::Uint32;
+ section_type = BinarySectionType::Vector;
+ }
+
+ if (!vector_length.has_value()) {
+ const uint64_t remaining = RemainingBytes(vector_offset);
+ SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ "4");
+
+ AddSection(
+ vector_offset,
+ MakeSingleRegionBinarySection(
+ std::string(table->name()->c_str()) + "." + field->name()->c_str(),
+ BinarySectionType::Vector,
+ MakeBinaryRegion(vector_offset, remaining,
+ BinaryRegionType::Unknown, remaining, 0,
+ vector_length_comment)));
+ return;
+ }
+
+ // Validate there are enough bytes left in the binary to process all the
+ // items.
+ const uint64_t last_item_offset =
+ vector_offset + vector_length_size_type +
+ vector_length.value() * GetElementSize(field);
+
+ if (!IsValidOffset(last_item_offset - 1)) {
+ SetError(vector_length_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+ AddSection(
+ vector_offset,
+ MakeSingleRegionBinarySection(
+ std::string(table->name()->c_str()) + "." + field->name()->c_str(),
+ BinarySectionType::Vector,
+ MakeBinaryRegion(vector_offset, vector_length_size_type,
+ region_type, 0, 0, vector_length_comment)));
+
+ return;
+ }
+
+ std::vector<BinaryRegion> regions;
+
+ regions.push_back(MakeBinaryRegion(vector_offset, vector_length_size_type,
+ region_type, 0, 0, vector_length_comment));
+ // Consume the vector length offset.
+ uint64_t offset = vector_offset + vector_length_size_type;
+
+ switch (field->type()->element()) {
+ case reflection::BaseType::Obj: {
+ const reflection::Object *object =
+ schema_->objects()->Get(field->type()->index());
+
+ if (object->is_struct()) {
+ // Vector of structs
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ // Structs are inline to the vector.
+ const uint64_t next_offset =
+ BuildStruct(offset, regions, "[" + NumToString(i) + "]", object);
+ if (next_offset == offset) { break; }
+ offset = next_offset;
+ }
+ } else {
+ // Vector of objects
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_object_comment;
+ vector_object_comment.type =
+ BinaryRegionCommentType::VectorTableValue;
+ vector_object_comment.index = i;
+
+ const auto table_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!table_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_object_comment));
+ break;
+ }
+
+ // The table offset is relative from the offset location itself.
+ const uint64_t table_offset = offset + table_relative_offset.value();
+
+ if (!IsValidOffset(table_offset)) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ if (table_offset == parent_table_offset) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_CYCLE_DETECTED);
+ // A cycle detected where a table vector field is pointing to
+ // itself. This should only happen in corrupted files.
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ table_offset, vector_object_comment));
+
+ // Consume the offset to the table.
+ offset += sizeof(uint32_t);
+
+ BuildTable(table_offset, BinarySectionType::Table, object);
+ }
+ }
+ } break;
+ case reflection::BaseType::String: {
+ // Vector of strings
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_object_comment;
+ vector_object_comment.type = BinaryRegionCommentType::VectorStringValue;
+ vector_object_comment.index = i;
+
+ const auto string_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!string_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_object_comment));
+ break;
+ }
+
+ // The string offset is relative from the offset location itself.
+ const uint64_t string_offset = offset + string_relative_offset.value();
+
+ if (!IsValidOffset(string_offset)) {
+ SetError(vector_object_comment,
+ BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ string_offset, vector_object_comment));
+
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ regions.push_back(MakeBinaryRegion(
+ offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+ string_offset, vector_object_comment));
+
+ BuildString(string_offset, table, field);
+
+ offset += sizeof(uint32_t);
+ }
+ } break;
+ case reflection::BaseType::Union: {
+ // Vector of unions
+ // Unions have both their realized type (uint8_t for now) that are
+ // stored separately. These are stored in the field->index() - 1
+ // location.
+ const uint16_t union_type_vector_id = field->id() - 1;
+
+ auto vtable_entry = vtable_fields.find(union_type_vector_id);
+ if (vtable_entry == vtable_fields.end()) {
+ // TODO(dbaileychess): need to capture this error condition.
+ break;
+ }
+
+ const uint64_t union_type_vector_field_offset =
+ parent_table_offset + vtable_entry->second.offset_from_table;
+
+ const auto union_type_vector_field_relative_offset =
+ ReadScalar<uint16_t>(union_type_vector_field_offset);
+
+ if (!union_type_vector_field_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+ BinaryRegionComment vector_union_comment;
+ vector_union_comment.type = BinaryRegionCommentType::VectorUnionValue;
+ SetError(vector_union_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown, remaining,
+ 0, vector_union_comment));
+
+ break;
+ }
+
+ // Get the offset to the first type (the + sizeof(uint32_t) is to skip
+ // over the vector length which we already know). Validation happens
+ // within the loop below.
+ const uint64_t union_type_vector_data_offset =
+ union_type_vector_field_offset +
+ union_type_vector_field_relative_offset.value() + sizeof(uint32_t);
+
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::VectorUnionValue;
+ comment.index = i;
+
+ const auto union_relative_offset = ReadScalar<uint32_t>(offset);
+ if (!union_relative_offset.has_value()) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+ regions.push_back(MakeBinaryRegion(offset, remaining,
+ BinaryRegionType::Unknown,
+ remaining, 0, comment));
+
+ break;
+ }
+
+ // The union offset is relative from the offset location itself.
+ const uint64_t union_offset = offset + union_relative_offset.value();
+
+ if (!IsValidOffset(union_offset)) {
+ SetError(comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ union_offset, comment));
+ continue;
+ }
+
+ const auto realized_type =
+ ReadScalar<uint8_t>(union_type_vector_data_offset + i);
+
+ if (!realized_type.has_value()) {
+ SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+ regions.push_back(MakeBinaryRegion(
+ offset, 0, BinaryRegionType::Unknown, 0, 0, comment));
+ continue;
+ }
+
+ if (!IsValidUnionValue(vtable_entry->second.field->type()->index(),
+ realized_type.value())) {
+ // We already export an error in the union type field, so just skip
+ // building the union itself and it will default to an unreference
+ // Binary section.
+ offset += sizeof(uint32_t);
+ continue;
+ }
+
+ const std::string enum_type =
+ BuildUnion(union_offset, realized_type.value(), field);
+
+ comment.default_value = "(`" + enum_type + "`)";
+ regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+ BinaryRegionType::UOffset, 0,
+ union_offset, comment));
+
+ offset += sizeof(uint32_t);
+ }
+ } break;
+ default: {
+ if (IsScalar(field->type()->element())) {
+ const BinaryRegionType binary_region_type =
+ GetRegionType(field->type()->element());
+
+ const uint64_t type_size = GetTypeSize(field->type()->element());
+
+ // TODO(dbaileychess): It might be nicer to user the
+ // BinaryRegion.array_length field to indicate this.
+ for (size_t i = 0; i < vector_length.value(); ++i) {
+ BinaryRegionComment vector_scalar_comment;
+ vector_scalar_comment.type = BinaryRegionCommentType::VectorValue;
+ vector_scalar_comment.index = i;
+
+ if (!IsValidRead(offset, type_size)) {
+ const uint64_t remaining = RemainingBytes(offset);
+
+ SetError(vector_scalar_comment,
+ BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+ std::to_string(type_size));
+
+ regions.push_back(
+ MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+ remaining, 0, vector_scalar_comment));
+ break;
+ }
+
+ if (IsUnionType(field->type()->element())) {
+ // This is a type for a union. Validate the value
+ const auto enum_value = ReadScalar<uint8_t>(offset);
+
+ // This should always have a value, due to the IsValidRead check
+ // above.
+ if (!IsValidUnionValue(field->type()->index(),
+ enum_value.value())) {
+ SetError(vector_scalar_comment,
+ BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+ regions.push_back(MakeBinaryRegion(offset, type_size,
+ binary_region_type, 0, 0,
+ vector_scalar_comment));
+ offset += type_size;
+ continue;
+ }
+ }
+
+ regions.push_back(MakeBinaryRegion(offset, type_size,
+ binary_region_type, 0, 0,
+ vector_scalar_comment));
+ offset += type_size;
+ }
+ }
+ } break;
+ }
+ AddSection(vector_offset,
+ MakeBinarySection(std::string(table->name()->c_str()) + "." +
+ field->name()->c_str(),
+ section_type, std::move(regions)));
+}
+
+std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,
+ const uint8_t realized_type,
+ const reflection::Field *const field) {
+ const reflection::Enum *next_enum =
+ schema_->enums()->Get(field->type()->index());
+
+ const reflection::EnumVal *enum_val = next_enum->values()->Get(realized_type);
+
+ if (ContainsSection(union_offset)) { return enum_val->name()->c_str(); }
+
+ const reflection::Type *union_type = enum_val->union_type();
+
+ if (union_type->base_type() == reflection::BaseType::Obj) {
+ const reflection::Object *object =
+ schema_->objects()->Get(union_type->index());
+
+ if (object->is_struct()) {
+ // Union of vectors point to a new Binary section
+ std::vector<BinaryRegion> regions;
+
+ BuildStruct(union_offset, regions, field->name()->c_str(), object);
+
+ AddSection(
+ union_offset,
+ MakeBinarySection(std::string(object->name()->c_str()) + "." +
+ field->name()->c_str(),
+ BinarySectionType::Union, std::move(regions)));
+ } else {
+ BuildTable(union_offset, BinarySectionType::Table, object);
+ }
+ }
+ // TODO(dbaileychess): handle the other union types.
+
+ return enum_val->name()->c_str();
+}
+
+void BinaryAnnotator::FixMissingRegions() {
+ std::vector<BinaryRegion> regions_to_insert;
+ for (auto &current_section : sections_) {
+ BinarySection &section = current_section.second;
+ if (section.regions.empty()) {
+ // TODO(dbaileychess): is this possible?
+ continue;
+ }
+
+ uint64_t offset = section.regions[0].offset + section.regions[0].length;
+ for (size_t i = 1; i < section.regions.size(); ++i) {
+ BinaryRegion &region = section.regions[i];
+
+ const uint64_t next_offset = region.offset;
+ if (!IsValidOffset(next_offset)) {
+ // TODO(dbaileychess): figure out how we get into this situation.
+ continue;
+ }
+
+ if (offset < next_offset) {
+ const uint64_t padding_bytes = next_offset - offset;
+
+ BinaryRegionComment comment;
+ comment.type = BinaryRegionCommentType::Padding;
+
+ if (IsNonZeroRegion(offset, padding_bytes, binary_)) {
+ SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+ regions_to_insert.push_back(
+ MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Unknown,
+ padding_bytes, 0, comment));
+ } else {
+ regions_to_insert.push_back(
+ MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Uint8,
+ padding_bytes, 0, comment));
+ }
+ }
+ offset = next_offset + region.length;
+ }
+
+ if (!regions_to_insert.empty()) {
+ section.regions.insert(section.regions.end(), regions_to_insert.begin(),
+ regions_to_insert.end());
+ std::stable_sort(section.regions.begin(), section.regions.end(),
+ BinaryRegionSort);
+ regions_to_insert.clear();
+ }
+ }
+}
+
+void BinaryAnnotator::FixMissingSections() {
+ uint64_t offset = 0;
+
+ std::vector<BinarySection> sections_to_insert;
+
+ for (auto &current_section : sections_) {
+ BinarySection &section = current_section.second;
+ const uint64_t section_start_offset = current_section.first;
+ const uint64_t section_end_offset =
+ section.regions.back().offset + section.regions.back().length;
+
+ if (offset < section_start_offset) {
+ // We are at an offset that is less then the current section.
+ const uint64_t pad_bytes = section_start_offset - offset + 1;
+
+ sections_to_insert.push_back(
+ GenerateMissingSection(offset - 1, pad_bytes, binary_));
+ }
+ offset = section_end_offset + 1;
+ }
+
+ // Handle the case where there are still bytes left in the binary that are
+ // unaccounted for.
+ if (offset < binary_length_) {
+ const uint64_t pad_bytes = binary_length_ - offset + 1;
+ sections_to_insert.push_back(
+ GenerateMissingSection(offset - 1, pad_bytes, binary_));
+ }
+
+ for (const BinarySection &section_to_insert : sections_to_insert) {
+ AddSection(section_to_insert.regions[0].offset, section_to_insert);
+ }
+}
+
+bool BinaryAnnotator::ContainsSection(const uint64_t offset) {
+ auto it = sections_.lower_bound(offset);
+ // If the section is found, check that it is exactly equal its offset.
+ if (it != sections_.end() && it->first == offset) { return true; }
+
+ // If this was the first section, there are no other previous sections to
+ // check.
+ if (it == sections_.begin()) { return false; }
+
+ // Go back one section.
+ --it;
+
+ // And check that if the offset is covered by the section.
+ return offset >= it->first && offset < it->second.regions.back().offset +
+ it->second.regions.back().length;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/binary_annotator.h b/contrib/libs/flatbuffers/src/binary_annotator.h
new file mode 100644
index 0000000000..df8a17bed4
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/binary_annotator.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2021 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_BINARY_ANNOTATOR_H_
+#define FLATBUFFERS_BINARY_ANNOTATOR_H_
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/stl_emulation.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+enum class BinaryRegionType {
+ Unknown = 0,
+ UOffset = 1,
+ SOffset = 2,
+ VOffset = 3,
+ Bool = 4,
+ Byte = 5,
+ Char = 6,
+ Uint8 = 7,
+ Int8 = 8,
+ Uint16 = 9,
+ Int16 = 10,
+ Uint32 = 11,
+ Int32 = 12,
+ Uint64 = 13,
+ Int64 = 14,
+ Float = 15,
+ Double = 16,
+ UType = 17,
+ UOffset64 = 18,
+};
+
+template<typename T>
+static inline std::string ToHex(T i, size_t width = sizeof(T)) {
+ std::stringstream stream;
+ stream << std::hex << std::uppercase << std::setfill('0')
+ << std::setw(static_cast<int>(width)) << i;
+ return stream.str();
+}
+
+// Specialized version for uint8_t that don't work well with std::hex.
+static inline std::string ToHex(uint8_t i) {
+ return ToHex<int>(static_cast<int>(i), 2);
+}
+
+enum class BinaryRegionStatus {
+ OK = 0,
+ WARN = 100,
+ WARN_NO_REFERENCES,
+ WARN_CORRUPTED_PADDING,
+ WARN_PADDING_LENGTH,
+ ERROR = 200,
+ // An offset is pointing outside the binary bounds.
+ ERROR_OFFSET_OUT_OF_BINARY,
+ // Expecting to read N bytes but not enough remain in the binary.
+ ERROR_INCOMPLETE_BINARY,
+ // When a length of a vtable/vector is longer than possible.
+ ERROR_LENGTH_TOO_LONG,
+ // When a length of a vtable/vector is shorter than possible.
+ ERROR_LENGTH_TOO_SHORT,
+ // A field mark required is not present in the vtable.
+ ERROR_REQUIRED_FIELD_NOT_PRESENT,
+ // A realized union type is not within the enum bounds.
+ ERROR_INVALID_UNION_TYPE,
+ // Occurs when there is a cycle in offsets.
+ ERROR_CYCLE_DETECTED,
+};
+
+enum class BinaryRegionCommentType {
+ Unknown = 0,
+ SizePrefix,
+ // The offset to the root table.
+ RootTableOffset,
+ // The optional 4-char file identifier.
+ FileIdentifier,
+ // Generic 0-filled padding
+ Padding,
+ // The size of the vtable.
+ VTableSize,
+ // The size of the referring table.
+ VTableRefferingTableLength,
+ // Offsets to vtable fields.
+ VTableFieldOffset,
+ // Offsets to unknown vtable fields.
+ VTableUnknownFieldOffset,
+ // The vtable offset of a table.
+ TableVTableOffset,
+ // A "inline" table field value.
+ TableField,
+ // A table field that is unknown.
+ TableUnknownField,
+ // A table field value that points to another section.
+ TableOffsetField,
+ // A struct field value.
+ StructField,
+ // A array field value.
+ ArrayField,
+ // The length of the string.
+ StringLength,
+ // The string contents.
+ StringValue,
+ // The explicit string terminator.
+ StringTerminator,
+ // The length of the vector (# of items).
+ VectorLength,
+ // A "inline" value of a vector.
+ VectorValue,
+ // A vector value that points to another section.
+ VectorTableValue,
+ VectorStringValue,
+ VectorUnionValue,
+};
+
+struct BinaryRegionComment {
+ BinaryRegionStatus status = BinaryRegionStatus::OK;
+
+ // If status is non OK, this may be filled in with additional details.
+ std::string status_message;
+
+ BinaryRegionCommentType type = BinaryRegionCommentType::Unknown;
+
+ std::string name;
+
+ std::string default_value;
+
+ size_t index = 0;
+};
+
+struct BinaryRegion {
+ // Offset into the binary where this region begins.
+ uint64_t offset = 0;
+
+ // The length of this region in bytes.
+ uint64_t length = 0;
+
+ // The underlying datatype of this region
+ BinaryRegionType type = BinaryRegionType::Unknown;
+
+ // If `type` is an array/vector, this is the number of those types this region
+ // encompasses.
+ uint64_t array_length = 0;
+
+ // If the is an offset to some other region, this is what it points to. The
+ // offset is relative to overall binary, not to this region.
+ uint64_t points_to_offset = 0;
+
+ // The comment on the region.
+ BinaryRegionComment comment;
+};
+
+enum class BinarySectionType {
+ Unknown = 0,
+ Header = 1,
+ Table = 2,
+ RootTable = 3,
+ VTable = 4,
+ Struct = 5,
+ String = 6,
+ Vector = 7,
+ Union = 8,
+ Padding = 9,
+ Vector64 = 10,
+};
+
+// A section of the binary that is grouped together in some logical manner, and
+// often is pointed too by some other offset BinaryRegion. Sections include
+// `tables`, `vtables`, `strings`, `vectors`, etc..
+struct BinarySection {
+ // User-specified name of the section, if applicable.
+ std::string name;
+
+ // The type of this section.
+ BinarySectionType type = BinarySectionType::Unknown;
+
+ // The binary regions that make up this section, in order of their offsets.
+ std::vector<BinaryRegion> regions;
+};
+
+inline static BinaryRegionType GetRegionType(reflection::BaseType base_type) {
+ switch (base_type) {
+ case reflection::UType: return BinaryRegionType::UType;
+ case reflection::Bool: return BinaryRegionType::Uint8;
+ case reflection::Byte: return BinaryRegionType::Uint8;
+ case reflection::UByte: return BinaryRegionType::Uint8;
+ case reflection::Short: return BinaryRegionType::Int16;
+ case reflection::UShort: return BinaryRegionType::Uint16;
+ case reflection::Int: return BinaryRegionType::Uint32;
+ case reflection::UInt: return BinaryRegionType::Uint32;
+ case reflection::Long: return BinaryRegionType::Int64;
+ case reflection::ULong: return BinaryRegionType::Uint64;
+ case reflection::Float: return BinaryRegionType::Float;
+ case reflection::Double: return BinaryRegionType::Double;
+ default: return BinaryRegionType::Unknown;
+ }
+}
+
+inline static std::string ToString(const BinaryRegionType type) {
+ switch (type) {
+ case BinaryRegionType::UOffset: return "UOffset32";
+ case BinaryRegionType::UOffset64: return "UOffset64";
+ case BinaryRegionType::SOffset: return "SOffset32";
+ case BinaryRegionType::VOffset: return "VOffset16";
+ case BinaryRegionType::Bool: return "bool";
+ case BinaryRegionType::Char: return "char";
+ case BinaryRegionType::Byte: return "int8_t";
+ case BinaryRegionType::Uint8: return "uint8_t";
+ case BinaryRegionType::Uint16: return "uint16_t";
+ case BinaryRegionType::Uint32: return "uint32_t";
+ case BinaryRegionType::Uint64: return "uint64_t"; ;
+ case BinaryRegionType::Int8: return "int8_t";
+ case BinaryRegionType::Int16: return "int16_t";
+ case BinaryRegionType::Int32: return "int32_t";
+ case BinaryRegionType::Int64: return "int64_t";
+ case BinaryRegionType::Double: return "double";
+ case BinaryRegionType::Float: return "float";
+ case BinaryRegionType::UType: return "UType8";
+ case BinaryRegionType::Unknown: return "?uint8_t";
+ default: return "todo";
+ }
+}
+
+class BinaryAnnotator {
+ public:
+ explicit BinaryAnnotator(const uint8_t *const bfbs,
+ const uint64_t bfbs_length,
+ const uint8_t *const binary,
+ const uint64_t binary_length,
+ const bool is_size_prefixed)
+ : bfbs_(bfbs),
+ bfbs_length_(bfbs_length),
+ schema_(reflection::GetSchema(bfbs)),
+ binary_(binary),
+ binary_length_(binary_length),
+ is_size_prefixed_(is_size_prefixed) {}
+
+ std::map<uint64_t, BinarySection> Annotate();
+
+ private:
+ struct VTable {
+ struct Entry {
+ const reflection::Field *field = nullptr;
+ uint16_t offset_from_table = 0;
+ };
+
+ const reflection::Object *referring_table = nullptr;
+
+ // Field ID -> {field def, offset from table}
+ std::map<uint16_t, Entry> fields;
+
+ uint16_t vtable_size = 0;
+ uint16_t table_size = 0;
+ };
+
+ uint64_t BuildHeader(uint64_t offset);
+
+ // VTables can be shared across instances or even across objects. This
+ // attempts to get an existing vtable given the offset and table type,
+ // otherwise it will built the vtable, memorize it, and return the built
+ // VTable. Returns nullptr if building the VTable fails.
+ VTable *GetOrBuildVTable(uint64_t offset, const reflection::Object *table,
+ uint64_t offset_of_referring_table);
+
+ void BuildTable(uint64_t offset, const BinarySectionType type,
+ const reflection::Object *table);
+
+ uint64_t BuildStruct(uint64_t offset, std::vector<BinaryRegion> &regions,
+ const std::string referring_field_name,
+ const reflection::Object *structure);
+
+ void BuildString(uint64_t offset, const reflection::Object *table,
+ const reflection::Field *field);
+
+ void BuildVector(uint64_t offset, const reflection::Object *table,
+ const reflection::Field *field, uint64_t parent_table_offset,
+ const std::map<uint16_t, VTable::Entry> vtable_fields);
+
+ std::string BuildUnion(uint64_t offset, uint8_t realized_type,
+ const reflection::Field *field);
+
+ void FixMissingRegions();
+ void FixMissingSections();
+
+ inline bool IsValidOffset(const uint64_t offset) const {
+ return offset < binary_length_;
+ }
+
+ // Determines if performing a GetScalar request for `T` at `offset` would read
+ // passed the end of the binary.
+ template<typename T> inline bool IsValidRead(const uint64_t offset) const {
+ return IsValidRead(offset, sizeof(T));
+ }
+
+ inline bool IsValidRead(const uint64_t offset, const uint64_t length) const {
+ return length < binary_length_ && IsValidOffset(offset + length - 1);
+ }
+
+ // Calculate the number of bytes remaining from the given offset. If offset is
+ // > binary_length, 0 is returned.
+ uint64_t RemainingBytes(const uint64_t offset) const {
+ return IsValidOffset(offset) ? binary_length_ - offset : 0;
+ }
+
+ template<typename T>
+ flatbuffers::Optional<T> ReadScalar(const uint64_t offset) const {
+ if (!IsValidRead<T>(offset)) { return flatbuffers::nullopt; }
+
+ return flatbuffers::ReadScalar<T>(binary_ + offset);
+ }
+
+ // Adds the provided `section` keyed by the `offset` it occurs at. If a
+ // section is already added at that offset, it doesn't replace the exisiting
+ // one.
+ void AddSection(const uint64_t offset, const BinarySection &section) {
+ sections_.insert(std::make_pair(offset, section));
+ }
+
+ bool IsInlineField(const reflection::Field *const field) {
+ if (field->type()->base_type() == reflection::BaseType::Obj) {
+ return schema_->objects()->Get(field->type()->index())->is_struct();
+ }
+ return IsScalar(field->type()->base_type());
+ }
+
+ bool IsUnionType(const reflection::BaseType type) {
+ return (type == reflection::BaseType::UType ||
+ type == reflection::BaseType::Union);
+ }
+
+ bool IsUnionType(const reflection::Field *const field) {
+ return IsUnionType(field->type()->base_type()) &&
+ field->type()->index() >= 0;
+ }
+
+ bool IsValidUnionValue(const reflection::Field *const field,
+ const uint8_t value) {
+ return IsUnionType(field) &&
+ IsValidUnionValue(field->type()->index(), value);
+ }
+
+ bool IsValidUnionValue(const uint32_t enum_id, const uint8_t value) {
+ if (enum_id >= schema_->enums()->size()) { return false; }
+
+ const reflection::Enum *enum_def = schema_->enums()->Get(enum_id);
+
+ if (enum_def == nullptr) { return false; }
+
+ return value < enum_def->values()->size();
+ }
+
+ uint64_t GetElementSize(const reflection::Field *const field) {
+ if (IsScalar(field->type()->element())) {
+ return GetTypeSize(field->type()->element());
+ }
+
+ switch (field->type()->element()) {
+ case reflection::BaseType::Obj: {
+ auto obj = schema_->objects()->Get(field->type()->index());
+ return obj->is_struct() ? obj->bytesize() : sizeof(uint32_t);
+ }
+ default: return sizeof(uint32_t);
+ }
+ }
+
+ bool ContainsSection(const uint64_t offset);
+
+ // The schema for the binary file
+ const uint8_t *bfbs_;
+ const uint64_t bfbs_length_;
+ const reflection::Schema *schema_;
+
+ // The binary data itself.
+ const uint8_t *binary_;
+ const uint64_t binary_length_;
+ const bool is_size_prefixed_;
+
+ // Map of binary offset to vtables, to dedupe vtables.
+ std::map<uint64_t, std::list<VTable>> vtables_;
+
+ // The annotated binary sections, index by their absolute offset.
+ std::map<uint64_t, BinarySection> sections_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BINARY_ANNOTATOR_H_
diff --git a/contrib/libs/flatbuffers/src/code_generators.cpp b/contrib/libs/flatbuffers/src/code_generators.cpp
index 745406ba95..c5efb222b1 100644
--- a/contrib/libs/flatbuffers/src/code_generators.cpp
+++ b/contrib/libs/flatbuffers/src/code_generators.cpp
@@ -30,6 +30,52 @@
namespace flatbuffers {
+namespace {
+
+static std::string JavaCSharpMakeRule(const bool java, const Parser &parser,
+ const std::string &path,
+ const std::string &file_name) {
+ const std::string file_extension = java ? ".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;
+}
+
+
+static 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;
+}
+
+} // namespace
+
+
+
+
void CodeWriter::operator+=(std::string text) {
if (!ignore_ident_ && !text.empty()) AppendIdent(stream_);
@@ -60,7 +106,7 @@ void CodeWriter::operator+=(std::string text) {
// Update the text to everything after the }}.
text = text.substr(end + 2);
}
- if (!text.empty() && string_back(text) == '\\') {
+ if (!text.empty() && text.back() == '\\') {
text.pop_back();
ignore_ident_ = true;
stream_ << text;
@@ -91,7 +137,8 @@ std::string BaseGenerator::NamespaceDir(const Parser &parser,
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 +=
+ !dasherize ? *it : ConvertCase(*it, Case::kDasher, Case::kUpperCamel);
namespace_dir += kPathSeparator;
EnsureDirExists(namespace_dir);
}
@@ -103,22 +150,6 @@ std::string BaseGenerator::NamespaceDir(const Namespace &ns,
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;
@@ -146,8 +177,9 @@ std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
return qualified_name + name;
}
-std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
- return WrapInNameSpace(def.defined_namespace, def.name);
+std::string BaseGenerator::WrapInNameSpace(const Definition &def,
+ const std::string &suffix) const {
+ return WrapInNameSpace(def.defined_namespace, def.name + suffix);
}
std::string BaseGenerator::GetNameSpace(const Definition &def) const {
@@ -314,46 +346,14 @@ 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 JavaMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ return JavaCSharpMakeRule(true, parser, path, file_name);
}
-
-std::string BinaryFileName(const Parser &parser, const std::string &path,
+std::string CSharpMakeRule(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;
+ return JavaCSharpMakeRule(false, parser, path, file_name);
}
bool GenerateBinary(const Parser &parser, const std::string &path,
diff --git a/contrib/libs/flatbuffers/src/file_binary_writer.cpp b/contrib/libs/flatbuffers/src/file_binary_writer.cpp
new file mode 100644
index 0000000000..69d83e77c9
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/file_binary_writer.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2023 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 <fstream>
+#include <set>
+#include <string>
+
+#include "flatbuffers/file_manager.h"
+
+namespace flatbuffers {
+
+class FileBinaryWriter : public FileManager {
+ public:
+ bool SaveFile(const std::string &absolute_file_name,
+ const std::string &content) override {
+ std::ofstream ofs(absolute_file_name, std::ofstream::binary);
+ if (!ofs.is_open()) return false;
+ ofs.write(content.c_str(), content.size());
+ return !ofs.bad();
+ }
+
+ bool Loadfile(const std::string &absolute_file_name, std::string *output) {
+ if (DirExists(absolute_file_name.c_str())) return false;
+ std::ifstream ifs(absolute_file_name, std::ifstream::binary);
+ if (!ifs.is_open()) return false;
+ // The fastest way to read a file into a string.
+ ifs.seekg(0, std::ios::end);
+ auto size = ifs.tellg();
+ (*output).resize(static_cast<size_t>(size));
+ ifs.seekg(0, std::ios::beg);
+ ifs.read(&(*output)[0], (*output).size());
+ return !ifs.bad();
+ }
+};
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp b/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
new file mode 100644
index 0000000000..fc4a4aa1ec
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/file_name_saving_file_manager.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2023 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 <fstream>
+#include <set>
+#include <string>
+
+#include "flatbuffers/file_manager.h"
+
+namespace flatbuffers {
+
+class FileNameSavingFileManager : public FileManager {
+ public:
+ FileNameSavingFileManager(std::set<std::string> file_names)
+ : file_names_(file_names) {}
+
+ bool SaveFile(const std::string &absolute_file_name,
+ const std::string &content) override {
+ (void)content;
+ auto pair = file_names_.insert(absolute_file_name);
+ // pair.second indicates whether the insertion is
+ // successful or not.
+ return pair.second;
+ }
+
+ bool Loadfile(const std::string &absolute_file_name, std::string *content) {
+ (void) absolute_file_name;
+ (void) content;
+ return false;
+ }
+
+ private:
+ std::set<std::string> file_names_;
+};
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/file_writer.cpp b/contrib/libs/flatbuffers/src/file_writer.cpp
new file mode 100644
index 0000000000..bd34545b00
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/file_writer.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 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 <fstream>
+#include <set>
+#include <string>
+
+#include "flatbuffers/file_manager.h"
+
+namespace flatbuffers {
+
+class FileWriter : public FileManager {
+ public:
+ bool SaveFile(const std::string &absolute_file_name,
+ const std::string &content) override {
+ std::ofstream ofs(absolute_file_name, std::ofstream::out);
+ if (!ofs.is_open()) return false;
+ ofs.write(content.c_str(), content.size());
+ return !ofs.bad();
+ }
+
+ bool Loadfile(const std::string &absolute_file_name, std::string *output) {
+ if (DirExists(absolute_file_name.c_str())) return false;
+ std::ifstream ifs(absolute_file_name, std::ifstream::in);
+ if (!ifs.is_open()) return false;
+ // This is slower, but works correctly on all platforms for text files.
+ std::ostringstream oss;
+ oss << ifs.rdbuf();
+ *output = oss.str();
+ return !ifs.bad();
+ }
+};
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/flatc.cpp b/contrib/libs/flatbuffers/src/flatc.cpp
index 221b88676d..a1501712e5 100644
--- a/contrib/libs/flatbuffers/src/flatc.cpp
+++ b/contrib/libs/flatbuffers/src/flatc.cpp
@@ -16,26 +16,38 @@
#include "flatbuffers/flatc.h"
+#include <algorithm>
+#include <limits>
#include <list>
+#include <memory>
+#include <sstream>
+
+#include "annotated_binary_text_gen.h"
+#include "binary_annotator.h"
+#include "flatbuffers/code_generator.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
namespace flatbuffers {
-const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
+static 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 {
+ const 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())) {
+
+ std::vector<const char *> inc_directories;
+ inc_directories.insert(inc_directories.end(), include_directories.begin(),
+ include_directories.end());
+ inc_directories.push_back(local_include_directory.c_str());
+ inc_directories.push_back(nullptr);
+
+ if (!parser.Parse(contents.c_str(), &inc_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,
@@ -56,181 +68,399 @@ void FlatCompiler::Error(const std::string &err, bool usage,
params_.error_fn(this, err, usage, show_exe_name);
}
-std::string FlatCompiler::GetUsageString(const char *program_name) const {
+const static FlatCOption flatc_options[] = {
+ { "o", "", "PATH", "Prefix PATH to all generated files." },
+ { "I", "", "PATH", "Search for includes in the specified path." },
+ { "M", "", "", "Print make rules for generated files." },
+ { "", "version", "", "Print the version number of flatc and exit." },
+ { "h", "help", "", "Prints this help text and exit." },
+ { "", "strict-json", "",
+ "Strict JSON: field names must be / will be quoted, no trailing commas in "
+ "tables/vectors." },
+ { "", "allow-non-utf8", "",
+ "Pass non-UTF-8 input through parser and emit nonstandard \\x escapes in "
+ "JSON. (Default is to raise parse error on non-UTF-8 input.)" },
+ { "", "natural-utf8", "",
+ "Output strings with UTF-8 as human-readable strings. By default, UTF-8 "
+ "characters are printed as \\uXXXX escapes." },
+ { "", "defaults-json", "",
+ "Output fields whose value is the default when writing JSON" },
+ { "", "unknown-json", "",
+ "Allow fields in JSON that are not defined in the schema. These fields "
+ "will be discared when generating binaries." },
+ { "", "no-prefix", "",
+ "Don't prefix enum values with the enum type in C++." },
+ { "", "scoped-enums", "",
+ "Use C++11 style scoped and strongly typed enums. Also implies "
+ "--no-prefix." },
+ { "", "no-emit-min-max-enum-values", "",
+ "Disable generation of MIN and MAX enumerated values for scoped enums "
+ "and prefixed enums." },
+ { "", "swift-implementation-only", "",
+ "Adds a @_implementationOnly to swift imports" },
+ { "", "gen-includes", "",
+ "(deprecated), this is the default behavior. If the original behavior is "
+ "required (no include statements) use --no-includes." },
+ { "", "no-includes", "",
+ "Don't generate include statements for included schemas the generated "
+ "file depends on (C++, Python, Proto-to-Fbs)." },
+ { "", "gen-mutable", "",
+ "Generate accessors that can mutate buffers in-place." },
+ { "", "gen-onefile", "",
+ "Generate a single output file for C#, Go, Java, Kotlin and Python. "
+ "Implies --no-include." },
+ { "", "gen-name-strings", "",
+ "Generate type name functions for C++ and Rust." },
+ { "", "gen-object-api", "", "Generate an additional object-based API." },
+ { "", "gen-compare", "", "Generate operator== for object-based API types." },
+ { "", "gen-nullable", "",
+ "Add Clang _Nullable for C++ pointer. or @Nullable for Java" },
+ { "", "java-package-prefix", "",
+ "Add a prefix to the generated package name for Java." },
+ { "", "java-checkerframework", "", "Add @Pure for Java." },
+ { "", "gen-generated", "", "Add @Generated annotation for Java." },
+ { "", "gen-jvmstatic", "",
+ "Add @JvmStatic annotation for Kotlin methods in companion object for "
+ "interop from Java to Kotlin." },
+ { "", "gen-all", "",
+ "Generate not just code for the current schema files, but for all files it "
+ "includes as well. If the language uses a single file for output (by "
+ "default the case for C++ and JS), all code will end up in this one "
+ "file." },
+ { "", "gen-json-emit", "",
+ "Generates encoding code which emits Flatbuffers into JSON" },
+ { "", "cpp-include", "", "Adds an #include in generated file." },
+ { "", "cpp-ptr-type", "T",
+ "Set object API pointer type (default std::unique_ptr)." },
+ { "", "cpp-str-type", "T",
+ "Set object API string type (default std::string). T::c_str(), T::length() "
+ "and T::empty() must be supported. The custom type also needs to be "
+ "constructible from std::string (see the --cpp-str-flex-ctor option to "
+ "change this behavior)" },
+ { "", "cpp-str-flex-ctor", "",
+ "Don't construct custom string types by passing std::string from "
+ "Flatbuffers, but (char* + length)." },
+ { "", "cpp-field-case-style", "STYLE",
+ "Generate C++ fields using selected case style. Supported STYLE values: * "
+ "'unchanged' - leave unchanged (default) * 'upper' - schema snake_case "
+ "emits UpperCamel; * 'lower' - schema snake_case emits lowerCamel." },
+ { "", "cpp-std", "CPP_STD",
+ "Generate a C++ code using features of selected C++ standard. Supported "
+ "CPP_STD values: * 'c++0x' - generate code compatible with old compilers; "
+ "'c++11' - use C++11 code generator (default); * 'c++17' - use C++17 "
+ "features in generated code (experimental)." },
+ { "", "cpp-static-reflection", "",
+ "When using C++17, generate extra code to provide compile-time (static) "
+ "reflection of Flatbuffers types. Requires --cpp-std to be \"c++17\" or "
+ "higher." },
+ { "", "object-prefix", "PREFIX",
+ "Customize class prefix for C++ object-based API." },
+ { "", "object-suffix", "SUFFIX",
+ "Customize class suffix for C++ object-based API. Default Value is "
+ "\"T\"." },
+ { "", "go-namespace", "", "Generate the overriding namespace in Golang." },
+ { "", "go-import", "IMPORT",
+ "Generate the overriding import for flatbuffers in Golang (default is "
+ "\"github.com/google/flatbuffers/go\")." },
+ { "", "go-module-name", "",
+ "Prefix local import paths of generated go code with the module name" },
+ { "", "raw-binary", "",
+ "Allow binaries without file_identifier to be read. This may crash flatc "
+ "given a mismatched schema." },
+ { "", "size-prefixed", "", "Input binaries are size prefixed buffers." },
+ { "", "proto-namespace-suffix", "SUFFIX",
+ "Add this namespace to any flatbuffers generated from protobufs." },
+ { "", "oneof-union", "", "Translate .proto oneofs to flatbuffer unions." },
+ { "", "keep-proto-id", "", "Keep protobuf field ids in generated fbs file." },
+ { "", "proto-id-gap", "",
+ "Action that should be taken when a gap between protobuf ids found. "
+ "Supported values: * "
+ "'nop' - do not care about gap * 'warn' - A warning message will be shown "
+ "about the gap in protobuf ids"
+ "(default) "
+ "* 'error' - An error message will be shown and the fbs generation will be "
+ "interrupted." },
+ { "", "grpc", "", "Generate GRPC interfaces for the specified languages." },
+ { "", "schema", "", "Serialize schemas instead of JSON (use with -b)." },
+ { "", "bfbs-filenames", "PATH",
+ "Sets the root path where reflection filenames in reflection.fbs are "
+ "relative to. The 'root' is denoted with `//`. E.g. if PATH=/a/b/c "
+ "then /a/d/e.fbs will be serialized as //../d/e.fbs. (PATH defaults to the "
+ "directory of the first provided schema file." },
+ { "", "bfbs-comments", "", "Add doc comments to the binary schema files." },
+ { "", "bfbs-builtins", "",
+ "Add builtin attributes to the binary schema files." },
+ { "", "bfbs-gen-embed", "",
+ "Generate code to embed the bfbs schema to the source." },
+ { "", "conform", "FILE",
+ "Specify a schema the following schemas should be an evolution of. Gives "
+ "errors if not." },
+ { "", "conform-includes", "PATH",
+ "Include path for the schema given with --conform PATH" },
+ { "", "filename-suffix", "SUFFIX",
+ "The suffix appended to the generated file names (Default is "
+ "'_generated')." },
+ { "", "filename-ext", "EXT",
+ "The extension appended to the generated file names. Default is "
+ "language-specific (e.g., '.h' for C++)" },
+ { "", "include-prefix", "PATH",
+ "Prefix this PATH to any generated include statements." },
+ { "", "keep-prefix", "",
+ "Keep original prefix of schema include statement." },
+ { "", "reflect-types", "",
+ "Add minimal type reflection to code generation." },
+ { "", "reflect-names", "", "Add minimal type/name reflection." },
+ { "", "rust-serialize", "",
+ "Implement serde::Serialize on generated Rust types." },
+ { "", "rust-module-root-file", "",
+ "Generate rust code in individual files with a module root file." },
+ { "", "root-type", "T", "Select or override the default root_type." },
+ { "", "require-explicit-ids", "",
+ "When parsing schemas, require explicit ids (id: x)." },
+ { "", "force-defaults", "",
+ "Emit default values in binary output from JSON" },
+ { "", "force-empty", "",
+ "When serializing from object API representation, force strings and "
+ "vectors to empty rather than null." },
+ { "", "force-empty-vectors", "",
+ "When serializing from object API representation, force vectors to empty "
+ "rather than null." },
+ { "", "flexbuffers", "",
+ "Used with \"binary\" and \"json\" options, it generates data using "
+ "schema-less FlexBuffers." },
+ { "", "no-warnings", "", "Inhibit all warnings messages." },
+ { "", "warnings-as-errors", "", "Treat all warnings as errors." },
+ { "", "cs-global-alias", "",
+ "Prepend \"global::\" to all user generated csharp classes and "
+ "structs." },
+ { "", "cs-gen-json-serializer", "",
+ "Allows (de)serialization of JSON text in the Object API. (requires "
+ "--gen-object-api)." },
+ { "", "json-nested-bytes", "",
+ "Allow a nested_flatbuffer field to be parsed as a vector of bytes "
+ "in JSON, which is unsafe unless checked by a verifier afterwards." },
+ { "", "ts-flat-files", "",
+ "Generate a single typescript file per .fbs file. Implies "
+ "ts_entry_points." },
+ { "", "ts-entry-points", "",
+ "Generate entry point typescript per namespace. Implies gen-all." },
+ { "", "annotate-sparse-vectors", "", "Don't annotate every vector element." },
+ { "", "annotate", "SCHEMA",
+ "Annotate the provided BINARY_FILE with the specified SCHEMA file." },
+ { "", "no-leak-private-annotation", "",
+ "Prevents multiple type of annotations within a Fbs SCHEMA file. "
+ "Currently this is required to generate private types in Rust" },
+ { "", "python-no-type-prefix-suffix", "",
+ "Skip emission of Python functions that are prefixed with typenames" },
+ { "", "python-typing", "", "Generate Python type annotations" },
+ { "", "file-names-only", "",
+ "Print out generated file names without writing to the files" },
+};
+
+auto cmp = [](FlatCOption a, FlatCOption b) { return a.long_opt < b.long_opt; };
+static std::set<FlatCOption, decltype(cmp)> language_options(cmp);
+
+static void AppendTextWrappedString(std::stringstream &ss, std::string &text,
+ size_t max_col, size_t start_col) {
+ size_t max_line_length = max_col - start_col;
+
+ if (text.length() > max_line_length) {
+ size_t ideal_break_location = text.rfind(' ', max_line_length);
+ size_t length = std::min(max_line_length, ideal_break_location);
+ ss << text.substr(0, length) << "\n";
+ ss << std::string(start_col, ' ');
+ std::string rest_of_description = text.substr(
+ ((ideal_break_location < max_line_length || text.at(length) == ' ')
+ ? length + 1
+ : length));
+ AppendTextWrappedString(ss, rest_of_description, max_col, start_col);
+ } else {
+ ss << text;
+ }
+}
+
+static void AppendOption(std::stringstream &ss, const FlatCOption &option,
+ size_t max_col, size_t min_col_for_description) {
+ size_t chars = 2;
+ ss << " ";
+ if (!option.short_opt.empty()) {
+ chars += 2 + option.short_opt.length();
+ ss << "-" << option.short_opt;
+ if (!option.long_opt.empty()) {
+ chars++;
+ ss << ",";
+ }
+ ss << " ";
+ }
+ if (!option.long_opt.empty()) {
+ chars += 3 + option.long_opt.length();
+ ss << "--" << option.long_opt << " ";
+ }
+ if (!option.parameter.empty()) {
+ chars += 1 + option.parameter.length();
+ ss << option.parameter << " ";
+ }
+ size_t start_of_description = chars;
+ if (start_of_description > min_col_for_description) {
+ ss << "\n";
+ start_of_description = min_col_for_description;
+ ss << std::string(start_of_description, ' ');
+ } else {
+ while (start_of_description < min_col_for_description) {
+ ss << " ";
+ start_of_description++;
+ }
+ }
+ if (!option.description.empty()) {
+ std::string description = option.description;
+ AppendTextWrappedString(ss, description, max_col, start_of_description);
+ }
+ ss << "\n";
+}
+
+static void AppendShortOption(std::stringstream &ss,
+ const FlatCOption &option) {
+ if (!option.short_opt.empty()) {
+ ss << "-" << option.short_opt;
+ if (!option.long_opt.empty()) { ss << "|"; }
+ }
+ if (!option.long_opt.empty()) { ss << "--" << option.long_opt; }
+}
+
+std::string FlatCompiler::GetShortUsageString(
+ const std::string &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];
+ ss << "Usage: " << program_name << " [";
+
+ for (const FlatCOption &option : language_options) {
+ AppendShortOption(ss, option);
+ ss << ", ";
+ }
- 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;
+ for (const FlatCOption &option : flatc_options) {
+ AppendShortOption(ss, option);
+ ss << ", ";
+ }
+
+ ss.seekp(-2, ss.cur);
+ ss << "]... FILE... [-- BINARY_FILE...]";
+ std::string help = ss.str();
+ std::stringstream ss_textwrap;
+ AppendTextWrappedString(ss_textwrap, help, 80, 0);
+ return ss_textwrap.str();
+}
+
+std::string FlatCompiler::GetUsageString(
+ const std::string &program_name) const {
+ std::stringstream ss;
+ ss << "Usage: " << program_name
+ << " [OPTION]... FILE... [-- BINARY_FILE...]\n";
+
+ for (const FlatCOption &option : language_options) {
+ AppendOption(ss, option, 80, 25);
+ }
+ ss << "\n";
- ss << " " << full_name.str() << " " << name << " " << help << ".\n";
+ for (const FlatCOption &option : flatc_options) {
+ AppendOption(ss, option, 80, 25);
}
- // 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
+ ss << "\n";
+
+ std::string files_description =
+ "FILEs may be schemas (must end in .fbs), binary schemas (must end in "
+ ".bfbs) or JSON files (conforming to preceding schema). BINARY_FILEs "
+ "after the -- must be binary flatbuffer format files. Output files are "
+ "named using the base file name of the input, and written to the current "
+ "directory or the path given by -o. example: " +
+ program_name + " -c -b schema1.fbs schema2.fbs data.json";
+ AppendTextWrappedString(ss, files_description, 80, 0);
+ ss << "\n";
return ss.str();
}
-int FlatCompiler::Compile(int argc, const char **argv) {
- if (params_.generators == nullptr || params_.num_generators == 0) {
- return 0;
+void FlatCompiler::AnnotateBinaries(const uint8_t *binary_schema,
+ const uint64_t binary_schema_size,
+ const FlatCOptions &options) {
+ const std::string &schema_filename = options.annotate_schema;
+
+ for (const std::string &filename : options.filenames) {
+ std::string binary_contents;
+ if (!flatbuffers::LoadFile(filename.c_str(), true, &binary_contents)) {
+ Warn("unable to load binary file: " + filename);
+ continue;
+ }
+
+ const uint8_t *binary =
+ reinterpret_cast<const uint8_t *>(binary_contents.c_str());
+ const size_t binary_size = binary_contents.size();
+ const bool is_size_prefixed = options.opts.size_prefixed;
+
+ flatbuffers::BinaryAnnotator binary_annotator(
+ binary_schema, binary_schema_size, binary, binary_size,
+ is_size_prefixed);
+
+ auto annotations = binary_annotator.Annotate();
+
+ flatbuffers::AnnotatedBinaryTextGenerator::Options text_gen_opts;
+ text_gen_opts.include_vector_contents =
+ options.annotate_include_vector_contents;
+
+ // TODO(dbaileychess): Right now we just support a single text-based
+ // output of the annotated binary schema, which we generate here. We
+ // could output the raw annotations instead and have third-party tools
+ // use them to generate their own output.
+ flatbuffers::AnnotatedBinaryTextGenerator text_generator(
+ text_gen_opts, annotations, binary, binary_size);
+
+ text_generator.Generate(filename, schema_filename);
}
+}
+
+FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
+ const char **argv) {
+ if (argc <= 1) { Error("Need to provide at least one argument."); }
+
+ FlatCOptions options;
+
+ options.program_name = std::string(argv[0]);
+
+ IDLOptions &opts = options.opts;
- 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++) {
+ for (int argi = 1; argi < argc; argi++) {
std::string arg = argv[argi];
if (arg[0] == '-') {
- if (filenames.size() && arg[1] != '-')
+ if (options.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(
+ options.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(
+ options.include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
- include_directories.push_back(
- include_directories_storage.back().c_str());
+ options.include_directories.push_back(
+ options.include_directories_storage.back().c_str());
+ } else if (arg == "--bfbs-filenames") {
+ if (++argi > argc) Error("missing path following: " + arg, true);
+ opts.project_root = argv[argi];
+ if (!DirExists(opts.project_root.c_str()))
+ Error(arg + " is not a directory: " + opts.project_root);
} else if (arg == "--conform") {
if (++argi >= argc) Error("missing path following: " + arg, true);
- conform_to_schema = flatbuffers::PosixPath(argv[argi]);
+ options.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(
+ options.include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
- conform_include_directories.push_back(
- include_directories_storage.back().c_str());
+ options.conform_include_directories.push_back(
+ options.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;
+ opts.keep_prefix = true;
} else if (arg == "--strict-json") {
opts.strict_json = true;
} else if (arg == "--allow-non-utf8") {
@@ -243,15 +473,22 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--go-import") {
if (++argi >= argc) Error("missing golang import" + arg, true);
opts.go_import = argv[argi];
+ } else if (arg == "--go-module-name") {
+ if (++argi >= argc) Error("missing golang module name" + arg, true);
+ opts.go_module_name = 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 == "--cpp-minify-enums") {
+ opts.cpp_minify_enums = true;
} else if (arg == "--scoped-enums") {
opts.prefixed_enums = false;
opts.scoped_enums = true;
+ } else if (arg == "--no-emit-min-max-enum-values") {
+ opts.emit_min_max_enum_values = false;
} else if (arg == "--no-union-value-namespacing") {
opts.union_value_namespacing = false;
} else if (arg == "--gen-mutable") {
@@ -275,12 +512,30 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.cpp_object_api_string_flexible_constructor = true;
} else if (arg == "--no-cpp-direct-copy") {
opts.cpp_direct_copy = false;
+ } else if (arg == "--cpp-field-case-style") {
+ if (++argi >= argc) Error("missing case style following: " + arg, true);
+ if (!strcmp(argv[argi], "unchanged"))
+ opts.cpp_object_api_field_case_style =
+ IDLOptions::CaseStyle_Unchanged;
+ else if (!strcmp(argv[argi], "upper"))
+ opts.cpp_object_api_field_case_style = IDLOptions::CaseStyle_Upper;
+ else if (!strcmp(argv[argi], "lower"))
+ opts.cpp_object_api_field_case_style = IDLOptions::CaseStyle_Lower;
+ else
+ Error("unknown case style: " + std::string(argv[argi]), true);
} else if (arg == "--gen-nullable") {
opts.gen_nullable = true;
+ } else if (arg == "--java-package-prefix") {
+ if (++argi >= argc) Error("missing prefix following: " + arg, true);
+ opts.java_package_prefix = argv[argi];
} else if (arg == "--java-checkerframework") {
opts.java_checkerframework = true;
} else if (arg == "--gen-generated") {
opts.gen_generated = true;
+ } else if (arg == "--swift-implementation-only") {
+ opts.swift_implementation_only = true;
+ } else if (arg == "--gen-json-emit") {
+ opts.gen_json_coders = true;
} else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following: " + arg, true);
opts.object_prefix = argv[argi];
@@ -297,28 +552,42 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.include_dependence_headers = false;
} else if (arg == "--gen-onefile") {
opts.one_file = true;
+ opts.include_dependence_headers = false;
} else if (arg == "--raw-binary") {
- raw_binary = true;
+ options.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;
+ options.binary_files_from = options.filenames.size();
} 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 == "--keep-proto-id") {
+ opts.keep_proto_id = true;
+ } else if (arg == "--proto-id-gap") {
+ if (++argi >= argc) Error("missing case style following: " + arg, true);
+ if (!strcmp(argv[argi], "nop"))
+ opts.proto_id_gap_action = IDLOptions::ProtoIdGapAction::NO_OP;
+ else if (!strcmp(argv[argi], "warn"))
+ opts.proto_id_gap_action = IDLOptions::ProtoIdGapAction::WARNING;
+ else if (!strcmp(argv[argi], "error"))
+ opts.proto_id_gap_action = IDLOptions::ProtoIdGapAction::ERROR;
+ else
+ Error("unknown case style: " + std::string(argv[argi]), true);
} else if (arg == "--schema") {
- schema_binary = true;
+ options.schema_binary = true;
} else if (arg == "-M") {
- print_make_rules = true;
+ options.print_make_rules = true;
} else if (arg == "--version") {
printf("flatc version %s\n", FLATC_VERSION());
exit(0);
+ } else if (arg == "--help" || arg == "-h") {
+ printf("%s\n", GetUsageString(options.program_name).c_str());
+ exit(0);
} else if (arg == "--grpc") {
- grpc_enabled = true;
+ options.grpc_enabled = true;
} else if (arg == "--bfbs-comments") {
opts.binary_schema_comments = true;
} else if (arg == "--bfbs-builtins") {
@@ -329,6 +598,10 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.mini_reflect = IDLOptions::kTypes;
} else if (arg == "--reflect-names") {
opts.mini_reflect = IDLOptions::kTypesAndNames;
+ } else if (arg == "--rust-serialize") {
+ opts.rust_serialize = true;
+ } else if (arg == "--rust-module-root-file") {
+ opts.rust_module_root_file = true;
} else if (arg == "--require-explicit-ids") {
opts.require_explicit_ids = true;
} else if (arg == "--root-type") {
@@ -357,6 +630,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.gen_jvmstatic = true;
} else if (arg == "--no-warnings") {
opts.no_warnings = true;
+ } else if (arg == "--warnings-as-errors") {
+ opts.warnings_as_errors = true;
} else if (arg == "--cpp-std") {
if (++argi >= argc)
Error("missing C++ standard specification" + arg, true);
@@ -365,69 +640,132 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.cpp_std = arg.substr(std::string("--cpp-std=").size());
} else if (arg == "--cpp-static-reflection") {
opts.cpp_static_reflection = true;
+ } else if (arg == "--cs-global-alias") {
+ opts.cs_global_alias = true;
+ } else if (arg == "--json-nested-bytes") {
+ opts.json_nested_legacy_flatbuffers = true;
+ } else if (arg == "--ts-flat-files") {
+ opts.ts_flat_files = true;
+ opts.ts_entry_points = true;
+ opts.generate_all = true;
+ } else if (arg == "--ts-entry-points") {
+ opts.ts_entry_points = true;
+ opts.generate_all = true;
+ } else if (arg == "--ts-no-import-ext") {
+ opts.ts_no_import_ext = true;
+ } else if (arg == "--no-leak-private-annotation") {
+ opts.no_leak_private_annotations = true;
+ } else if (arg == "--python-no-type-prefix-suffix") {
+ opts.python_no_type_prefix_suffix = true;
+ } else if (arg == "--python-typing") {
+ opts.python_typing = true;
+ } else if (arg == "--annotate-sparse-vectors") {
+ options.annotate_include_vector_contents = false;
+ } else if (arg == "--annotate") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ options.annotate_schema = flatbuffers::PosixPath(argv[argi]);
+ } else if (arg == "--file-names-only") {
+ // TODO (khhn): Provide 2 implementation
+ options.file_names_only = 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;
- }
+ if (arg == "--proto") { opts.proto_mode = true; }
+
+ auto code_generator_it = code_generators_.find(arg);
+ if (code_generator_it == code_generators_.end()) {
+ Error("unknown commandline argument: " + arg, true);
+ return options;
}
- Error("unknown commandline argument: " + arg, true);
- found:;
+
+ std::shared_ptr<CodeGenerator> code_generator =
+ code_generator_it->second;
+
+ // TODO(derekbailey): remove in favor of just checking if
+ // generators.empty().
+ options.any_generator = true;
+ opts.lang_to_generate |= code_generator->Language();
+
+ auto is_binary_schema = code_generator->SupportsBfbsGeneration();
+ opts.binary_schema_comments = is_binary_schema;
+ options.requires_bfbs = is_binary_schema;
+ options.generators.push_back(std::move(code_generator));
}
} else {
- filenames.push_back(flatbuffers::PosixPath(argv[argi]));
+ options.filenames.push_back(flatbuffers::PosixPath(argv[argi]));
}
}
- if (!filenames.size()) Error("missing input files", false, true);
+ return options;
+}
+
+void FlatCompiler::ValidateOptions(const FlatCOptions &options) {
+ const IDLOptions &opts = options.opts;
+
+ if (!options.filenames.size()) Error("missing input files", false, true);
if (opts.proto_mode) {
- if (any_generator)
+ if (options.any_generator)
Error("cannot generate code directly from .proto files", true);
- } else if (!any_generator && conform_to_schema.empty()) {
+ } else if (!options.any_generator && options.conform_to_schema.empty() &&
+ options.annotate_schema.empty()) {
Error("no options: specify at least one generator.", true);
}
+ if (opts.cs_gen_json_serializer && !opts.generate_object_based_api) {
+ Error(
+ "--cs-gen-json-serializer requires --gen-object-api to be set as "
+ "well.");
+ }
+}
+
+flatbuffers::Parser FlatCompiler::GetConformParser(
+ const FlatCOptions &options) {
flatbuffers::Parser conform_parser;
- if (!conform_to_schema.empty()) {
+ if (!options.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::LoadFile(options.conform_to_schema.c_str(), true,
+ &contents)) {
+ Error("unable to load schema: " + options.conform_to_schema);
+ }
- if (flatbuffers::GetExtension(conform_to_schema) ==
+ if (flatbuffers::GetExtension(options.conform_to_schema) ==
reflection::SchemaExtension()) {
- LoadBinarySchema(conform_parser, conform_to_schema, contents);
+ LoadBinarySchema(conform_parser, options.conform_to_schema, contents);
} else {
- ParseFile(conform_parser, conform_to_schema, contents,
- conform_include_directories);
+ ParseFile(conform_parser, options.conform_to_schema, contents,
+ options.conform_include_directories);
}
}
+ return conform_parser;
+}
- std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
+std::unique_ptr<Parser> FlatCompiler::GenerateCode(const FlatCOptions &options,
+ Parser &conform_parser) {
+ std::unique_ptr<Parser> parser =
+ std::unique_ptr<Parser>(new Parser(options.opts));
+
+ for (auto file_it = options.filenames.begin();
+ file_it != options.filenames.end(); ++file_it) {
+ IDLOptions opts = options.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;
+ bool is_binary = static_cast<size_t>(file_it - options.filenames.begin()) >=
+ options.binary_files_from;
auto ext = flatbuffers::GetExtension(filename);
- auto is_schema = ext == "fbs" || ext == "proto";
- auto is_binary_schema = ext == reflection::SchemaExtension();
+ const bool is_schema = ext == "fbs" || ext == "proto";
+ if (is_schema && opts.project_root.empty()) {
+ opts.project_root = StripFileName(filename);
+ }
+ const bool 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) {
+ if (!options.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.
@@ -453,26 +791,30 @@ int FlatCompiler::Compile(int argc, const char **argv) {
contents.length() != strlen(contents.c_str())) {
Error("input file appears to be binary: " + filename, true);
}
- if (is_schema) {
+ if (is_schema || is_binary_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));
+ parser.reset(new Parser(opts));
}
+ // Try to parse the file contents (binary schema/flexbuffer/textual
+ // schema)
if (is_binary_schema) {
- LoadBinarySchema(*parser.get(), filename, contents);
- }
- if (opts.use_flexbuffers) {
+ LoadBinarySchema(*parser, filename, contents);
+ } else 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());
+ auto data = reinterpret_cast<const uint8_t *>(contents.c_str());
+ auto size = contents.size();
+ std::vector<uint8_t> reuse_tracker;
+ if (!flexbuffers::VerifyBuffer(data, size, &reuse_tracker))
+ Error("flexbuffers file failed to verify: " + filename, false);
+ parser->flex_root_ = flexbuffers::GetRoot(data, size);
} else {
parser->flex_builder_.Clear();
- ParseFile(*parser.get(), filename, contents, include_directories);
+ ParseFile(*parser, filename, contents, options.include_directories);
}
} else {
- ParseFile(*parser.get(), filename, contents, include_directories);
+ ParseFile(*parser, filename, contents, options.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.
@@ -481,56 +823,78 @@ int FlatCompiler::Compile(int argc, const char **argv) {
true);
}
}
- if ((is_schema || is_binary_schema) && !conform_to_schema.empty()) {
+ if ((is_schema || is_binary_schema) &&
+ !options.conform_to_schema.empty()) {
auto err = parser->ConformTo(conform_parser);
- if (!err.empty()) Error("schemas don\'t conform: " + err);
+ if (!err.empty()) Error("schemas don\'t conform: " + err, false);
}
- if (schema_binary || opts.binary_schema_gen_embed) {
+ if (options.schema_binary || opts.binary_schema_gen_embed) {
parser->Serialize();
}
- if (schema_binary) {
+ if (options.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);
+ // If one of the generators uses bfbs, serialize the parser and get
+ // the serialized buffer and length.
+ const uint8_t *bfbs_buffer = nullptr;
+ int64_t bfbs_length = 0;
+ if (options.requires_bfbs) {
+ parser->Serialize();
+ bfbs_buffer = parser->builder_.GetBufferPointer();
+ bfbs_length = parser->builder_.GetSize();
+ }
+
+ for (const std::shared_ptr<CodeGenerator> &code_generator :
+ options.generators) {
+ if (options.print_make_rules) {
+ std::string make_rule;
+ const CodeGenerator::Status status = code_generator->GenerateMakeRule(
+ *parser, options.output_path, filename, make_rule);
+ if (status == CodeGenerator::Status::OK && !make_rule.empty()) {
+ printf("%s\n",
+ flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str());
+ } else {
+ Error("Cannot generate make rule for " +
+ code_generator->LanguageName());
+ }
+ } else {
+ flatbuffers::EnsureDirExists(options.output_path);
+
+ // Prefer bfbs generators if present.
+ if (code_generator->SupportsBfbsGeneration()) {
+ const CodeGenerator::Status status =
+ code_generator->GenerateCode(bfbs_buffer, bfbs_length);
+ if (status != CodeGenerator::Status::OK) {
+ Error("Unable to generate " + code_generator->LanguageName() +
+ " for " + filebase + code_generator->status_detail +
+ " using bfbs generator.");
}
} 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 ((!code_generator->IsSchemaOnly() ||
+ (is_schema || is_binary_schema)) &&
+ code_generator->GenerateCode(*parser, options.output_path,
+ filebase) !=
+ CodeGenerator::Status::OK) {
+ Error("Unable to generate " + code_generator->LanguageName() +
+ " for " + filebase + code_generator->status_detail);
}
}
- 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 (options.grpc_enabled) {
+ const CodeGenerator::Status status = code_generator->GenerateGrpcCode(
+ *parser, options.output_path, filebase);
+
+ if (status == CodeGenerator::Status::NOT_IMPLEMENTED) {
+ Warn("GRPC interface generator not implemented for " +
+ code_generator->LanguageName());
+ } else if (status == CodeGenerator::Status::ERROR) {
+ Error("Unable to generate GRPC interface for " +
+ code_generator->LanguageName());
}
}
}
@@ -542,13 +906,111 @@ int FlatCompiler::Compile(int argc, const char **argv) {
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 parser;
+}
+
+int FlatCompiler::Compile(const FlatCOptions &options) {
+ // TODO(derekbailey): change to std::optional<Parser>
+ Parser conform_parser = GetConformParser(options);
+
+ // TODO(derekbailey): split to own method.
+ if (!options.annotate_schema.empty()) {
+ const std::string ext = flatbuffers::GetExtension(options.annotate_schema);
+ if (!(ext == reflection::SchemaExtension() || ext == "fbs")) {
+ Error("Expected a `.bfbs` or `.fbs` schema, got: " +
+ options.annotate_schema);
+ }
+
+ const bool is_binary_schema = ext == reflection::SchemaExtension();
+
+ std::string schema_contents;
+ if (!flatbuffers::LoadFile(options.annotate_schema.c_str(),
+ /*binary=*/is_binary_schema, &schema_contents)) {
+ Error("unable to load schema: " + options.annotate_schema);
+ }
+
+ const uint8_t *binary_schema = nullptr;
+ uint64_t binary_schema_size = 0;
+
+ IDLOptions binary_opts;
+ binary_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
+ Parser parser(binary_opts);
+
+ if (is_binary_schema) {
+ binary_schema =
+ reinterpret_cast<const uint8_t *>(schema_contents.c_str());
+ binary_schema_size = schema_contents.size();
+ } else {
+ // If we need to generate the .bfbs file from the provided schema file
+ // (.fbs)
+ ParseFile(parser, options.annotate_schema, schema_contents,
+ options.include_directories);
+ parser.Serialize();
+
+ binary_schema = parser.builder_.GetBufferPointer();
+ binary_schema_size = parser.builder_.GetSize();
+ }
+
+ if (binary_schema == nullptr || !binary_schema_size) {
+ Error("could not parse a value binary schema from: " +
+ options.annotate_schema);
+ }
+
+ // Annotate the provided files with the binary_schema.
+ AnnotateBinaries(binary_schema, binary_schema_size, options);
+
+ // We don't support doing anything else after annotating a binary.
+ return 0;
+ }
+
+ if (options.generators.empty()) {
+ Error("No generator registered");
+ return -1;
+ }
+
+ std::unique_ptr<Parser> parser = GenerateCode(options, conform_parser);
+
+ for (const auto &code_generator : options.generators) {
+ if (code_generator->SupportsRootFileGeneration()) {
+ code_generator->GenerateRootFile(*parser, options.output_path);
+ }
+ }
+
return 0;
}
+bool FlatCompiler::RegisterCodeGenerator(
+ const FlatCOption &option, std::shared_ptr<CodeGenerator> code_generator) {
+ if (!option.short_opt.empty() &&
+ code_generators_.find("-" + option.short_opt) != code_generators_.end()) {
+ Error("multiple generators registered under: -" + option.short_opt, false,
+ false);
+ return false;
+ }
+
+ if (!option.short_opt.empty()) {
+ code_generators_["-" + option.short_opt] = code_generator;
+ }
+
+ if (!option.long_opt.empty() &&
+ code_generators_.find("--" + option.long_opt) != code_generators_.end()) {
+ Error("multiple generators registered under: --" + option.long_opt, false,
+ false);
+ return false;
+ }
+
+ if (!option.long_opt.empty()) {
+ code_generators_["--" + option.long_opt] = code_generator;
+ }
+
+ language_options.insert(option);
+
+ return true;
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/flatc_main.cpp b/contrib/libs/flatbuffers/src/flatc_main.cpp
index 31ccbc7185..f2dde958d3 100644
--- a/contrib/libs/flatbuffers/src/flatc_main.cpp
+++ b/contrib/libs/flatbuffers/src/flatc_main.cpp
@@ -14,8 +14,32 @@
* limitations under the License.
*/
+#include <cstdio>
+#include <memory>
+
+#include "bfbs_gen_lua.h"
+#include "bfbs_gen_nim.h"
+#include "flatbuffers/base.h"
+#include "flatbuffers/code_generator.h"
#include "flatbuffers/flatc.h"
#include "flatbuffers/util.h"
+#include "idl_gen_binary.h"
+#include "idl_gen_cpp.h"
+ #include "idl_gen_cpp_yandex_maps_iter.h"
+#include "idl_gen_csharp.h"
+#include "idl_gen_dart.h"
+#include "idl_gen_fbs.h"
+#include "idl_gen_go.h"
+#include "idl_gen_java.h"
+#include "idl_gen_json_schema.h"
+#include "idl_gen_kotlin.h"
+#include "idl_gen_lobster.h"
+#include "idl_gen_php.h"
+#include "idl_gen_python.h"
+#include "idl_gen_rust.h"
+#include "idl_gen_swift.h"
+#include "idl_gen_text.h"
+#include "idl_gen_ts.h"
static const char *g_program_name = nullptr;
@@ -23,16 +47,16 @@ 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());
+ fprintf(stderr, "\nwarning:\n %s\n\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());
+ fprintf(stderr, "%s\n", flatc->GetShortUsageString(g_program_name).c_str());
}
+ fprintf(stderr, "\nerror:\n %s\n\n", err.c_str());
exit(1);
}
@@ -47,75 +71,115 @@ void LogCompilerError(const std::string &err) {
} // namespace flatbuffers
int main(int argc, const char *argv[]) {
- // Prevent Appveyor-CI hangs.
- flatbuffers::SetupDefaultCRTReportMode();
+ const std::string flatbuffers_version(flatbuffers::FLATBUFFERS_VERSION());
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);
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{
+ "b", "binary", "",
+ "Generate wire format binaries for any data definitions" },
+ flatbuffers::NewBinaryCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "c", "cpp", "",
+ "Generate C++ headers for tables/structs" },
+ flatbuffers::NewCppCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "n", "csharp", "",
+ "Generate C# classes for tables/structs" },
+ flatbuffers::NewCSharpCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "d", "dart", "",
+ "Generate Dart classes for tables/structs" },
+ flatbuffers::NewDartCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "proto", "",
+ "Input is a .proto, translate to .fbs" },
+ flatbuffers::NewFBSCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "g", "go", "",
+ "Generate Go files for tables/structs" },
+ flatbuffers::NewGoCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "j", "java", "",
+ "Generate Java classes for tables/structs" },
+ flatbuffers::NewJavaCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "jsonschema", "", "Generate Json schema" },
+ flatbuffers::NewJsonSchemaCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "kotlin", "",
+ "Generate Kotlin classes for tables/structs" },
+ flatbuffers::NewKotlinCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "lobster", "",
+ "Generate Lobster files for tables/structs" },
+ flatbuffers::NewLobsterCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "l", "lua", "",
+ "Generate Lua files for tables/structs" },
+ flatbuffers::NewLuaBfbsGenerator(flatbuffers_version));
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "nim", "",
+ "Generate Nim files for tables/structs" },
+ flatbuffers::NewNimBfbsGenerator(flatbuffers_version));
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "p", "python", "",
+ "Generate Python files for tables/structs" },
+ flatbuffers::NewPythonCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "php", "",
+ "Generate PHP files for tables/structs" },
+ flatbuffers::NewPhpCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "r", "rust", "",
+ "Generate Rust files for tables/structs" },
+ flatbuffers::NewRustCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{
+ "t", "json", "", "Generate text output for any data definitions" },
+ flatbuffers::NewTextCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "swift", "",
+ "Generate Swift files for tables/structs" },
+ flatbuffers::NewSwiftCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "", "yandex-maps-iter", "",
+ "Generate C++ template headers for tables/structs" },
+ flatbuffers::NewCppYandexMapsIterCodeGenerator());
+
+ flatc.RegisterCodeGenerator(
+ flatbuffers::FlatCOption{ "T", "ts", "",
+ "Generate TypeScript code for tables/structs" },
+ flatbuffers::NewTsCodeGenerator());
+
+ // Create the FlatC options by parsing the command line arguments.
+ const flatbuffers::FlatCOptions &options =
+ flatc.ParseFromCommandLineArguments(argc, argv);
+
+ // Compile with the extracted FlatC options.
+ return flatc.Compile(options);
}
diff --git a/contrib/libs/flatbuffers/src/idl_gen_binary.cpp b/contrib/libs/flatbuffers/src/idl_gen_binary.cpp
new file mode 100644
index 0000000000..feb4e2f55e
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_binary.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 "idl_gen_binary.h"
+
+#include <limits>
+#include <memory>
+#include <string>
+#include <unordered_set>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flatc.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+namespace {
+
+class BinaryCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateBinary(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ // Generate code from the provided `buffer` of given `length`. The buffer is a
+ // serialized reflection.fbs.
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = BinaryMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return false; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kBinary; }
+
+ std::string LanguageName() const override { return "binary"; }
+};
+
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewBinaryCodeGenerator() {
+ return std::unique_ptr<BinaryCodeGenerator>(new BinaryCodeGenerator());
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_binary.h b/contrib/libs/flatbuffers/src/idl_gen_binary.h
new file mode 100644
index 0000000000..a7c93b9d9b
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_binary.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 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_GEN_BINARY_H_
+#define FLATBUFFERS_IDL_GEN_BINARY_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Binary code generator.
+std::unique_ptr<CodeGenerator> NewBinaryCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_BINARY_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
index a33697eaed..6e22c9d219 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
@@ -16,8 +16,15 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_cpp.h"
+
+#include <limits>
+#include <memory>
+#include <string>
#include <unordered_set>
+#include <utility>
+#include "flatbuffers/base.h"
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flatc.h"
@@ -57,9 +64,8 @@ static std::string GenIncludeGuard(const std::string &file_name,
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 + "_";
+ for (const std::string &component : name_space.components) {
+ guard += component + "_";
}
// Anything extra to add to the guard?
if (!postfix.empty()) { guard += postfix + "_"; }
@@ -68,6 +74,18 @@ static std::string GenIncludeGuard(const std::string &file_name,
return guard;
}
+static bool IsVectorOfPointers(const FieldDef &field) {
+ const auto &type = field.value.type;
+ const auto &vector_type = type.VectorType();
+ return IsVector(type) && vector_type.base_type == BASE_TYPE_STRUCT &&
+ !vector_type.struct_def->fixed && !field.native_inline;
+}
+
+static bool IsPointer(const FieldDef &field) {
+ return field.value.type.base_type == BASE_TYPE_STRUCT &&
+ !IsStruct(field.value.type);
+}
+
namespace cpp {
enum CppStandard { CPP_STD_X0 = 0, CPP_STD_11, CPP_STD_17 };
@@ -75,7 +93,7 @@ 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>
+ kArrayArgModeSpanStatic, // generate ::flatbuffers::span<T,N>
};
// Extension of IDLOptions for cpp-generator.
@@ -88,6 +106,21 @@ struct IDLOptionsCpp : public IDLOptions {
: IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {}
};
+// Iterates over all the fields of the object first by Offset type (Offset64
+// before Offset32) and then by definition order.
+static void ForAllFieldsOrderedByOffset(
+ const StructDef &object, std::function<void(const FieldDef *field)> func) {
+ // Loop over all the fields and call the func on all offset64 fields.
+ for (const FieldDef *field_def : object.fields.vec) {
+ if (field_def->offset64) { func(field_def); }
+ }
+ // Loop over all the fields a second time and call the func on all offset
+ // fields.
+ for (const FieldDef *field_def : object.fields.vec) {
+ if (!field_def->offset64) { func(field_def); }
+ }
+}
+
class CppGenerator : public BaseGenerator {
public:
CppGenerator(const Parser &parser, const std::string &path,
@@ -199,40 +232,125 @@ class CppGenerator : public BaseGenerator {
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
+ // Adds code to check that the included flatbuffers.h is of the same version
+ // as the generated code. This check currently looks for exact version match,
+ // as we would guarantee that they are compatible, but in theory a newer
+ // version of flatbuffers.h should work with a old code gen if we do proper
+ // backwards support.
+ void GenFlatbuffersVersionCheck() {
+ code_ +=
+ "// Ensure the included flatbuffers.h is the same version as when this "
+ "file was";
+ code_ += "// generated, otherwise it may not be compatible.";
+ code_ += "static_assert(FLATBUFFERS_VERSION_MAJOR == " +
+ std::to_string(FLATBUFFERS_VERSION_MAJOR) + " &&";
+ code_ += " FLATBUFFERS_VERSION_MINOR == " +
+ std::to_string(FLATBUFFERS_VERSION_MINOR) + " &&";
+ code_ += " FLATBUFFERS_VERSION_REVISION == " +
+ std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
+ code_ += " \"Non-compatible flatbuffers version included\");";
+ }
+
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 (const std::string &native_included_file :
+ parser_.native_included_files_) {
+ code_ += "#include \"" + native_included_file + "\"";
}
}
- 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++;
+
+ // Get the directly included file of the file being parsed.
+ std::vector<IncludedFile> included_files(parser_.GetIncludedFiles());
+
+ // We are safe to sort them alphabetically, since there shouldn't be any
+ // interdependence between them.
+ std::stable_sort(included_files.begin(), included_files.end());
+
+ for (const IncludedFile &included_file : included_files) {
+ // Get the name of the included file as defined by the schema, and strip
+ // the .fbs extension.
+ const std::string name_without_ext =
+ StripExtension(included_file.schema_name);
+
+ // If we are told to keep the prefix of the included schema, leave it
+ // unchanged, otherwise strip the leading path off so just the "basename"
+ // of the include is retained.
+ const std::string basename =
+ opts_.keep_prefix ? name_without_ext : StripPath(name_without_ext);
+
+ code_ += "#include \"" +
+ GeneratedFileName(opts_.include_prefix, basename, opts_) + "\"";
+ }
+
+ if (!parser_.native_included_files_.empty() || !included_files.empty()) {
+ code_ += "";
}
- if (num_includes) code_ += "";
+ }
+
+ void MarkIf64BitBuilderIsNeeded() {
+ if (needs_64_bit_builder_) { return; }
+ for (auto t : parser_.structs_.vec) {
+ if (t == nullptr) continue;
+ for (auto f : t->fields.vec) {
+ if (f == nullptr) continue;
+ if (f->offset64) {
+ needs_64_bit_builder_ = true;
+ break;
+ }
+ }
+ }
+ }
+
+ std::string GetBuilder() {
+ return std::string("::flatbuffers::FlatBufferBuilder") +
+ (needs_64_bit_builder_ ? "64" : "");
}
void GenExtraIncludes() {
- for (std::size_t i = 0; i < opts_.cpp_includes.size(); ++i) {
- code_ += "#include \"" + opts_.cpp_includes[i] + "\"";
+ for (const std::string &cpp_include : opts_.cpp_includes) {
+ code_ += "#include \"" + cpp_include + "\"";
}
if (!opts_.cpp_includes.empty()) { code_ += ""; }
}
+ void GenEmbeddedIncludes() {
+ if (parser_.opts.binary_schema_gen_embed && parser_.root_struct_def_) {
+ const std::string file_path =
+ GeneratedFileName(opts_.include_prefix, file_name_ + "_bfbs", opts_);
+ code_ += "// For access to the binary schema that produced this file.";
+ code_ += "#include \"" + file_path + "\"";
+ code_ += "";
+ }
+ }
+
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : name + "_";
}
+ std::string Name(const FieldDef &field) const {
+ // the union type field suffix is immutable.
+ static size_t union_suffix_len = strlen(UnionTypeFieldSuffix());
+ const bool is_union_type = field.value.type.base_type == BASE_TYPE_UTYPE;
+ // early return if no case transformation required
+ if (opts_.cpp_object_api_field_case_style ==
+ IDLOptions::CaseStyle_Unchanged)
+ return EscapeKeyword(field.name);
+ std::string name = field.name;
+ // do not change the case style of the union type field suffix
+ if (is_union_type) {
+ FLATBUFFERS_ASSERT(name.length() > union_suffix_len);
+ name.erase(name.length() - union_suffix_len, union_suffix_len);
+ }
+ if (opts_.cpp_object_api_field_case_style == IDLOptions::CaseStyle_Upper)
+ name = ConvertCase(name, Case::kUpperCamel);
+ else if (opts_.cpp_object_api_field_case_style ==
+ IDLOptions::CaseStyle_Lower)
+ name = ConvertCase(name, Case::kLowerCamel);
+ // restore the union field type suffix
+ if (is_union_type) name.append(UnionTypeFieldSuffix(), union_suffix_len);
+ return EscapeKeyword(name);
+ }
+
std::string Name(const Definition &def) const {
return EscapeKeyword(def.name);
}
@@ -259,6 +377,11 @@ class CppGenerator : public BaseGenerator {
code_ += "#pragma clang system_header\n\n";
}
+ code_ += "#include \"flatbuffers/flatbuffers.h\"";
+ code_ += "";
+ GenFlatbuffersVersionCheck();
+ code_ += "";
+
SetNameSpace(struct_def.defined_namespace);
auto name = Name(struct_def);
code_.SetValue("STRUCT_NAME", name);
@@ -306,6 +429,9 @@ class CppGenerator : public BaseGenerator {
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
+ // Check if we require a 64-bit flatbuffer builder.
+ MarkIf64BitBuilderIsNeeded();
+
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
@@ -320,28 +446,30 @@ class CppGenerator : public BaseGenerator {
code_ += "#include <contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h>";
if (parser_.uses_flexbuffers_) {
code_ += "#include <contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h>";
+ code_ += "#include \"flatbuffers/flex_flat_util.h\"";
}
code_ += "";
+ GenFlatbuffersVersionCheck();
+ code_ += "";
if (opts_.include_dependence_headers) { GenIncludeDependencies(); }
GenExtraIncludes();
+ GenEmbeddedIncludes();
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;";
+ for (const auto &struct_def : parser_.structs_.vec) {
+ 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 + ";"; }
+ auto nativeName = NativeName(Name(*struct_def), struct_def, opts_);
+ if (!struct_def->fixed) { code_ += "struct " + nativeName + ";"; }
}
code_ += "";
}
@@ -349,12 +477,10 @@ class CppGenerator : public BaseGenerator {
// 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_);
+ for (const auto &struct_def : parser_.structs_.vec) {
+ 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 " +
@@ -367,80 +493,64 @@ class CppGenerator : public BaseGenerator {
// 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);
+ for (const auto &struct_def : parser_.structs_.vec) {
+ 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);
+ for (const auto &enum_def : parser_.enums_.vec) {
+ 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 (const auto &struct_def : parser_.structs_.vec) {
+ 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 (const auto &struct_def : parser_.structs_.vec) {
+ 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);
+ for (const auto &struct_def : parser_.structs_.vec) {
+ 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);
+ for (const auto &enum_def : parser_.enums_.vec) {
+ 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);
+ for (const auto &enum_def : parser_.enums_.vec) {
+ 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);
+ for (const auto &struct_def : parser_.structs_.vec) {
+ if (!struct_def->generated) {
+ SetNameSpace(struct_def->defined_namespace);
+ GenMiniReflect(struct_def, nullptr);
}
}
}
@@ -456,13 +566,15 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name);
code_.SetValue("NULLABLE_EXT", NullableExtension());
+ code_.SetValue(
+ "SIZE_T", needs_64_bit_builder_ ? ",::flatbuffers::uoffset64_t" : "");
// 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_ += " return ::flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
code_ += "}";
code_ += "";
@@ -471,14 +583,29 @@ class CppGenerator : public BaseGenerator {
"const {{CPP_NAME}} "
"*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
"*buf) {";
- code_ += " return flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);";
+ code_ +=
+ " return "
+ "::flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>(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_ +=
+ " return ::flatbuffers::GetMutableRoot<{{STRUCT_NAME}}>(buf);";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline \\";
+ code_ +=
+ "{{CPP_NAME}} "
+ "*{{NULLABLE_EXT}}GetMutableSizePrefixed{{STRUCT_NAME}}(void "
+ "*buf) {";
+ code_ +=
+ " return "
+ "::flatbuffers::GetMutableSizePrefixedRoot<{{CPP_NAME}}{{SIZE_T}}>("
+ "buf);";
code_ += "}";
code_ += "";
}
@@ -493,10 +620,20 @@ class CppGenerator : public BaseGenerator {
// Check if a buffer has the identifier.
code_ += "inline \\";
code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const void *buf) {";
- code_ += " return flatbuffers::BufferHasIdentifier(";
+ code_ += " return ::flatbuffers::BufferHasIdentifier(";
code_ += " buf, {{STRUCT_NAME}}Identifier());";
code_ += "}";
code_ += "";
+
+ // Check if a size-prefixed buffer has the identifier.
+ code_ += "inline \\";
+ code_ +=
+ "bool SizePrefixed{{STRUCT_NAME}}BufferHasIdentifier(const void "
+ "*buf) {";
+ code_ += " return ::flatbuffers::BufferHasIdentifier(";
+ code_ += " buf, {{STRUCT_NAME}}Identifier(), true);";
+ code_ += "}";
+ code_ += "";
}
// The root verifier.
@@ -507,15 +644,16 @@ class CppGenerator : public BaseGenerator {
}
code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
- code_ += " flatbuffers::Verifier &verifier) {";
+ 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_ += " ::flatbuffers::Verifier &verifier) {";
code_ +=
- " return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
+ " return "
+ "verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}{{SIZE_T}}>({{ID}});";
code_ += "}";
code_ += "";
@@ -529,8 +667,8 @@ class CppGenerator : public BaseGenerator {
// 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) {";
+ code_ += " " + GetBuilder() + " &fbb,";
+ code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length())
code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
else
@@ -539,8 +677,8 @@ class CppGenerator : public BaseGenerator {
code_ += "";
code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer(";
- code_ += " flatbuffers::FlatBufferBuilder &fbb,";
- code_ += " flatbuffers::Offset<{{CPP_NAME}}> root) {";
+ code_ += " " + GetBuilder() + " &fbb,";
+ code_ += " ::flatbuffers::Offset<{{CPP_NAME}}> root) {";
if (parser_.file_identifier_.length())
code_ += " fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());";
else
@@ -558,7 +696,8 @@ class CppGenerator : public BaseGenerator {
code_ += "inline {{UNPACK_RETURN}} UnPack{{STRUCT_NAME}}(";
code_ += " const void *buf,";
- code_ += " const flatbuffers::resolver_function_t *res = nullptr) {";
+ code_ +=
+ " const ::flatbuffers::resolver_function_t *res = nullptr) {";
code_ += " return {{UNPACK_TYPE}}\\";
code_ += "(Get{{STRUCT_NAME}}(buf)->UnPack(res));";
code_ += "}";
@@ -566,7 +705,8 @@ class CppGenerator : public BaseGenerator {
code_ += "inline {{UNPACK_RETURN}} UnPackSizePrefixed{{STRUCT_NAME}}(";
code_ += " const void *buf,";
- code_ += " const flatbuffers::resolver_function_t *res = nullptr) {";
+ code_ +=
+ " const ::flatbuffers::resolver_function_t *res = nullptr) {";
code_ += " return {{UNPACK_TYPE}}\\";
code_ += "(GetSizePrefixed{{STRUCT_NAME}}(buf)->UnPack(res));";
code_ += "}";
@@ -597,6 +737,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptionsCpp opts_;
const TypedFloatConstantGenerator float_const_gen_;
+ bool needs_64_bit_builder_ = false;
const Namespace *CurrentNameSpace() const { return cur_name_space_; }
@@ -614,17 +755,16 @@ class CppGenerator : public BaseGenerator {
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; }
+ for (auto &field : type.struct_def->fields.vec) {
+ 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);
+ return (opts_.scoped_enums && IsEnum(type)) ||
+ (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 = "") {
@@ -635,19 +775,11 @@ class CppGenerator : public BaseGenerator {
// 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 StringOf(type.base_type);
}
// Return a C++ pointer type, specialized to the actual struct/table types,
@@ -655,12 +787,16 @@ class CppGenerator : public BaseGenerator {
std::string GenTypePointer(const Type &type) const {
switch (type.base_type) {
case BASE_TYPE_STRING: {
- return "flatbuffers::String";
+ return "::flatbuffers::String";
}
+ case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeWire(
type.VectorType(), "", VectorElementUserFacing(type.VectorType()));
- return "flatbuffers::Vector<" + type_name + ">";
+ return "::flatbuffers::Vector" +
+ std::string((type.base_type == BASE_TYPE_VECTOR64) ? "64<"
+ : "<") +
+ type_name + ">";
}
case BASE_TYPE_STRUCT: {
return WrapInNameSpace(*type.struct_def);
@@ -676,13 +812,15 @@ class CppGenerator : public BaseGenerator {
// 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 {
+ bool user_facing_type,
+ bool _64_bit_offset = false) 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 "::flatbuffers::Offset" + std::string(_64_bit_offset ? "64" : "") +
+ "<" + GenTypePointer(type) + ">" + postfix;
}
}
@@ -694,7 +832,7 @@ class CppGenerator : public BaseGenerator {
} else if (IsStruct(type)) {
return GenTypePointer(type);
} else {
- return "flatbuffers::uoffset_t";
+ return "::flatbuffers::uoffset_t";
}
}
@@ -727,9 +865,8 @@ class CppGenerator : public BaseGenerator {
}
bool FlexibleStringConstructor(const FieldDef *field) {
- auto attr = field
- ? (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr)
- : false;
+ auto attr = field != nullptr &&
+ (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr);
auto ret = attr ? attr : opts_.cpp_object_api_string_flexible_constructor;
return ret && NativeString(field) !=
"std::string"; // Only for custom string types.
@@ -757,18 +894,19 @@ class CppGenerator : public BaseGenerator {
return ptr_type == "naked" ? "" : ".get()";
}
- std::string GenOptionalNull() { return "flatbuffers::nullopt"; }
+ std::string GenOptionalNull() { return "::flatbuffers::nullopt"; }
std::string GenOptionalDecl(const Type &type) {
- return "flatbuffers::Optional<" + GenTypeBasic(type, true) + ">";
+ return "::flatbuffers::Optional<" + GenTypeBasic(type, true) + ">";
}
std::string GenTypeNative(const Type &type, bool invector,
- const FieldDef &field) {
+ const FieldDef &field, bool forcopy = false) {
switch (type.base_type) {
case BASE_TYPE_STRING: {
return NativeString(&field);
}
+ case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeNative(type.VectorType(), true, field);
if (type.struct_def &&
@@ -777,23 +915,25 @@ class CppGenerator : public BaseGenerator {
type.struct_def->attributes.Lookup("native_custom_alloc");
return "std::vector<" + type_name + "," +
native_custom_alloc->constant + "<" + type_name + ">>";
- } else
+ } 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) {
+ if (invector || field.native_inline || forcopy) {
return type_name;
} else {
return GenTypeNativePtr(type_name, &field, false);
}
} else {
- return GenTypeNativePtr(
- WrapNativeNameInNameSpace(*type.struct_def, opts_), &field,
- false);
+ const auto nn = WrapNativeNameInNameSpace(*type.struct_def, opts_);
+ return (forcopy || field.native_inline)
+ ? nn
+ : GenTypeNativePtr(nn, &field, false);
}
}
case BASE_TYPE_UNION: {
@@ -833,10 +973,10 @@ class CppGenerator : public BaseGenerator {
}
std::string GenTypeSpan(const Type &type, bool immutable, size_t extent) {
- // Generate "flatbuffers::span<const U, extent>".
+ // Generate "::flatbuffers::span<const U, extent>".
FLATBUFFERS_ASSERT(IsSeries(type) && "unexpected type");
auto element_type = type.VectorType();
- std::string text = "flatbuffers::span<";
+ std::string text = "::flatbuffers::span<";
text += immutable ? "const " : "";
if (IsScalar(element_type.base_type)) {
text += GenTypeBasic(element_type, IsEnum(element_type));
@@ -856,7 +996,7 @@ class CppGenerator : public BaseGenerator {
break;
}
}
- if (extent != flatbuffers::dynamic_extent) {
+ if (extent != dynamic_extent) {
text += ", ";
text += NumToString(extent);
}
@@ -887,13 +1027,13 @@ class CppGenerator : public BaseGenerator {
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;
+ std::string name = ev.union_type.struct_def->name;
if (native_type) {
- name = NativeName(name, ev.union_type.struct_def, opts);
+ name = NativeName(std::move(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";
+ return native_type ? "std::string" : "::flatbuffers::String";
} else {
FLATBUFFERS_ASSERT(false);
return Name(ev);
@@ -902,48 +1042,51 @@ class CppGenerator : public BaseGenerator {
std::string UnionVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + Name(enum_def) +
- "(flatbuffers::Verifier &verifier, const void *obj, " +
+ "(::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)";
+ const std::string name = Name(enum_def);
+ const std::string &type = opts_.scoped_enums ? name : "uint8_t";
+ return "bool Verify" + name + "Vector" +
+ "(::flatbuffers::Verifier &verifier, " +
+ "const ::flatbuffers::Vector<::flatbuffers::Offset<void>> "
+ "*values, " +
+ "const ::flatbuffers::Vector<" + type + "> *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)";
+ " 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" +
+ return "::flatbuffers::Offset<void> " +
+ (inclass ? "" : Name(enum_def) + "Union::") + "Pack(" +
+ GetBuilder() + " &_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 " +
+ return "::flatbuffers::Offset<" + Name(struct_def) + "> Create" +
+ Name(struct_def) + "(" + GetBuilder() + " &_fbb, const " +
NativeName(Name(struct_def), &struct_def, opts) +
- " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
+ " *_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<" +
+ return std::string(inclass ? "static " : "") + "::flatbuffers::Offset<" +
Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") +
- "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "const " +
+ "Pack(" + GetBuilder() + " &_fbb, " + "const " +
NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
- "const flatbuffers::rehasher_function_t *_rehasher" +
+ "const ::flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ")";
}
@@ -951,7 +1094,7 @@ class CppGenerator : public BaseGenerator {
const IDLOptions &opts) {
return NativeName(Name(struct_def), &struct_def, opts) + " *" +
(inclass ? "" : Name(struct_def) + "::") +
- "UnPack(const flatbuffers::resolver_function_t *_resolver" +
+ "UnPack(const ::flatbuffers::resolver_function_t *_resolver" +
(inclass ? " = nullptr" : "") + ") const";
}
@@ -959,13 +1102,13 @@ class CppGenerator : public BaseGenerator {
const IDLOptions &opts) {
return "void " + (inclass ? "" : Name(struct_def) + "::") + "UnPackTo(" +
NativeName(Name(struct_def), &struct_def, opts) + " *" +
- "_o, const flatbuffers::resolver_function_t *_resolver" +
+ "_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_ += "inline const ::flatbuffers::TypeTable *{{NAME}}TypeTable();";
code_ += "";
}
@@ -981,11 +1124,9 @@ class CppGenerator : public BaseGenerator {
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);
+ for (const auto &field : struct_def->fields.vec) {
+ names.push_back(Name(*field));
+ types.push_back(field->value.type);
}
} else {
for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
@@ -999,8 +1140,7 @@ class CppGenerator : public BaseGenerator {
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;
+ for (auto &type : types) {
if (!ts.empty()) ts += ",\n ";
auto is_vector = IsVector(type);
auto is_array = IsArray(type);
@@ -1009,10 +1149,9 @@ class CppGenerator : public BaseGenerator {
? 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) : "";
+ 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) {
@@ -1027,24 +1166,24 @@ class CppGenerator : public BaseGenerator {
}
}
if (is_array) { array_sizes.push_back(type.fixed_length); }
- ts += "{ flatbuffers::" + std::string(ElementaryTypeNames()[et]) + ", " +
- NumToString(is_vector || is_array) + ", " + NumToString(ref_idx) +
- " }";
+ 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) {
+ for (auto &type_ref : type_refs) {
if (!rs.empty()) rs += ",\n ";
- rs += *it + "TypeTable";
+ rs += type_ref + "TypeTable";
}
std::string as;
- for (auto it = array_sizes.begin(); it != array_sizes.end(); ++it) {
- as += NumToString(*it);
+ for (auto &array_size : array_sizes) {
+ as += NumToString(array_size);
as += ", ";
}
std::string ns;
- for (auto it = names.begin(); it != names.end(); ++it) {
+ for (auto &name : names) {
if (!ns.empty()) ns += ",\n ";
- ns += "\"" + *it + "\"";
+ ns += "\"" + name + "\"";
}
std::string vs;
const auto consecutive_enum_from_zero =
@@ -1059,10 +1198,8 @@ class CppGenerator : public BaseGenerator {
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);
+ for (const auto field : struct_def->fields.vec) {
+ vs += NumToString(field->value.offset);
vs += ", ";
}
vs += NumToString(struct_def->bytesize);
@@ -1072,14 +1209,14 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("ARRAYSIZES", as);
code_.SetValue("NAMES", ns);
code_.SetValue("VALUES", vs);
- code_ += "inline const flatbuffers::TypeTable *{{NAME}}TypeTable() {";
+ code_ += "inline const ::flatbuffers::TypeTable *{{NAME}}TypeTable() {";
if (num_fields) {
- code_ += " static const flatbuffers::TypeCode type_codes[] = {";
+ code_ += " static const ::flatbuffers::TypeCode type_codes[] = {";
code_ += " {{TYPES}}";
code_ += " };";
}
if (!type_refs.empty()) {
- code_ += " static const flatbuffers::TypeFunction type_refs[] = {";
+ code_ += " static const ::flatbuffers::TypeFunction type_refs[] = {";
code_ += " {{REFS}}";
code_ += " };";
}
@@ -1097,8 +1234,8 @@ class CppGenerator : public BaseGenerator {
code_ += " {{NAMES}}";
code_ += " };";
}
- code_ += " static const flatbuffers::TypeTable tt = {";
- code_ += std::string(" flatbuffers::{{SEQ_TYPE}}, {{NUM_FIELDS}}, ") +
+ 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, ") +
@@ -1126,17 +1263,21 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("SEP", ",");
auto add_sep = false;
- for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
- const auto &ev = **it;
+ for (const auto ev : enum_def.Vals()) {
if (add_sep) code_ += "{{SEP}}";
- GenComment(ev.doc_comment, " ");
- code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev)));
+ GenComment(ev->doc_comment, " ");
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(*ev)));
code_.SetValue("VALUE",
- NumToStringCpp(enum_def.ToString(ev),
+ NumToStringCpp(enum_def.ToString(*ev),
enum_def.underlying_type.base_type));
code_ += " {{KEY}} = {{VALUE}}\\";
add_sep = true;
}
+ if (opts_.cpp_minify_enums) {
+ code_ += "";
+ code_ += "};";
+ return;
+ }
const EnumVal *minv = enum_def.MinValue();
const EnumVal *maxv = enum_def.MaxValue();
@@ -1144,6 +1285,8 @@ class CppGenerator : public BaseGenerator {
FLATBUFFERS_ASSERT(minv && maxv);
code_.SetValue("SEP", ",\n");
+
+ // MIN & MAX are useless for bit_flags
if (enum_def.attributes.Lookup("bit_flags")) {
code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE"));
code_.SetValue("VALUE", "0");
@@ -1154,7 +1297,7 @@ class CppGenerator : public BaseGenerator {
NumToStringCpp(enum_def.AllFlags(),
enum_def.underlying_type.base_type));
code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
- } else { // MIN & MAX are useless for bit_flags
+ } else if (opts_.emit_min_max_enum_values) {
code_.SetValue("KEY", GenEnumValDecl(enum_def, "MIN"));
code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*minv)));
code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
@@ -1172,8 +1315,173 @@ class CppGenerator : public BaseGenerator {
"FLATBUFFERS_DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
}
code_ += "";
+ GenEnumArray(enum_def);
+ GenEnumStringTable(enum_def);
+
+ // 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_ += "";
+ }
+ }
- // Generate an array of all enumeration values
+ GenEnumObjectBasedAPI(enum_def);
+
+ if (enum_def.is_union) {
+ code_ += UnionVerifySignature(enum_def) + ";";
+ code_ += UnionVectorVerifySignature(enum_def) + ";";
+ code_ += "";
+ }
+ }
+
+ // Generate a union type and a trait type for it.
+ void GenEnumObjectBasedAPI(const EnumDef &enum_def) {
+ if (!(opts_.generate_object_based_api && enum_def.is_union)) { return; }
+ code_.SetValue("NAME", Name(enum_def));
+ FLATBUFFERS_ASSERT(enum_def.Lookup("NONE"));
+ code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.Lookup("NONE")));
+
+ if (!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 {{NAME}}UnionTraits {";
+ } else {
+ auto name = GetUnionElement(ev, true, opts_);
+ code_ += "template<> struct {{NAME}}UnionTraits<" + name + "> {";
+ }
+
+ auto value = GetEnumValUse(enum_def, ev);
+ code_ += " static const {{ENUM_NAME}} enum_value = " + value + ";";
+ code_ += "};";
+ code_ += "";
+ }
+ }
+
+ 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_ += " template <typename T>";
+ code_ += " void Set(T&& val) {";
+ code_ += " typedef typename std::remove_reference<T>::type RT;";
+ code_ += " Reset();";
+ code_ += " type = {{NAME}}UnionTraits<RT>::enum_value;";
+ code_ += " if (type != {{NONE}}) {";
+ code_ += " value = new RT(std::forward<T>(val));";
+ code_ += " }";
+ code_ += " }";
+ code_ += "";
+ }
+ code_ += " " + UnionUnPackSignature(enum_def, true) + ";";
+ code_ += " " + UnionPackSignature(enum_def, true) + ";";
+ code_ += "";
+
+ for (const auto ev : enum_def.Vals()) {
+ 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_ += "";
+
+ GenEnumEquals(enum_def);
+ }
+
+ void GenEnumEquals(const EnumDef &enum_def) {
+ 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 (const auto &ev : enum_def.Vals()) {
+ 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_ += "";
+ }
+ }
+
+ // Generate an array of all enumeration values
+ void GenEnumArray(const EnumDef &enum_def) {
auto num_fields = NumToString(enum_def.size());
code_ += "inline const {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" +
num_fields + "] {";
@@ -1188,11 +1496,13 @@ class CppGenerator : public BaseGenerator {
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.
+ // Generate a string table for enum values.
+ // Problem is, if values are very sparse that could generate huge tables.
+ // Ideally in that case we generate a map lookup instead, but for the moment
+ // we simply don't output a table at all.
+ void GenEnumStringTable(const EnumDef &enum_def) {
auto range = enum_def.Distance();
// Average distance between values above which we consider a table
// "too sparse". Change at will.
@@ -1203,14 +1513,12 @@ class CppGenerator : public BaseGenerator {
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) {
+ for (const auto &enum_value : enum_def.Vals()) {
+ for (auto k = enum_def.Distance(val, enum_value); k > 1; --k) {
code_ += " \"\",";
}
- val = ev;
- code_ += " \"" + Name(*ev) + "\",";
+ val = enum_value;
+ code_ += " \"" + Name(*enum_value) + "\",";
}
code_ += " nullptr";
code_ += " };";
@@ -1221,7 +1529,7 @@ class CppGenerator : public BaseGenerator {
code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
- code_ += " if (flatbuffers::IsOutRange(e, " +
+ code_ += " if (::flatbuffers::IsOutRange(e, " +
GetEnumValUse(enum_def, *enum_def.MinValue()) + ", " +
GetEnumValUse(enum_def, *enum_def.MaxValue()) +
")) return \"\";";
@@ -1238,164 +1546,16 @@ class CppGenerator : public BaseGenerator {
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) + "\";";
+ for (const auto &ev : enum_def.Vals()) {
+ 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) {
@@ -1419,9 +1579,11 @@ class CppGenerator : public BaseGenerator {
" auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (ev.union_type.struct_def->fixed) {
+ code_.SetValue("ALIGN",
+ NumToString(ev.union_type.struct_def->minalign));
code_ +=
- " return verifier.Verify<{{TYPE}}>(static_cast<const "
- "uint8_t *>(obj), 0);";
+ " return verifier.VerifyField<{{TYPE}}>("
+ "static_cast<const uint8_t *>(obj), 0, {{ALIGN}});";
} else {
code_ += getptr;
code_ += " return verifier.VerifyTable(ptr);";
@@ -1447,7 +1609,8 @@ class CppGenerator : public BaseGenerator {
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_ +=
+ " 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))) {";
@@ -1461,6 +1624,7 @@ class CppGenerator : public BaseGenerator {
if (opts_.generate_object_based_api) {
// Generate union Unpack() and Pack() functions.
code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
+ code_ += " (void)resolver;";
code_ += " switch (type) {";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
@@ -1491,6 +1655,7 @@ class CppGenerator : public BaseGenerator {
code_ += "";
code_ += "inline " + UnionPackSignature(enum_def, false) + " {";
+ code_ += " (void)_rehasher;";
code_ += " switch (type) {";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
@@ -1526,23 +1691,20 @@ class CppGenerator : public BaseGenerator {
"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_));
+ for (const auto &ev : enum_def.Vals()) {
+ 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) {
+ if (opts_.g_cpp_std < cpp::CPP_STD_11 &&
+ 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) {
+ for (const auto &field : ev->union_type.struct_def->fields.vec) {
+ if (!field->deprecated && field->value.type.struct_def &&
+ !field->native_inline) {
copyable = false;
break;
}
@@ -1621,7 +1783,7 @@ class CppGenerator : public BaseGenerator {
if (!opts_.generate_name_strings) { return; }
auto fullname = struct_def.defined_namespace->GetFullyQualifiedName(name);
code_.SetValue("NAME", fullname);
- code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR");
+ code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR_CPP11");
code_ += " static {{CONSTEXPR}} const char *GetFullyQualifiedName() {";
code_ += " return \"{{NAME}}\";";
code_ += " }";
@@ -1659,6 +1821,8 @@ class CppGenerator : public BaseGenerator {
} else {
return "0";
}
+ } else if (IsStruct(type) && (field.value.constant == "0")) {
+ return "nullptr";
} else {
return GenDefaultConstant(field);
}
@@ -1676,7 +1840,8 @@ class CppGenerator : public BaseGenerator {
if (IsStruct(vtype)) {
type = WrapInNameSpace(*vtype.struct_def);
} else {
- type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
+ type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype),
+ field.offset64);
}
if (TypeHasKey(vtype)) {
code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
@@ -1690,7 +1855,8 @@ class CppGenerator : public BaseGenerator {
if (field.IsScalarOptional())
code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " ");
else
- code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true));
+ code_.SetValue("PARAM_TYPE",
+ GenTypeWire(type, " ", true, field.offset64));
}
code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
}
@@ -1699,11 +1865,11 @@ class CppGenerator : public BaseGenerator {
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 ||
+ (!IsVector(field.value.type) ||
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 =
+ const std::string &full_type =
(cpp_type
? (IsVector(field.value.type)
? "std::vector<" +
@@ -1713,7 +1879,7 @@ class CppGenerator : public BaseGenerator {
: GenTypeNativePtr(cpp_type->constant, &field, false))
: type + " ");
// Generate default member initializers for >= C++11.
- std::string field_di = "";
+ std::string field_di;
if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
field_di = "{}";
auto native_default = field.attributes.Lookup("native_default");
@@ -1735,13 +1901,47 @@ class CppGenerator : public BaseGenerator {
}
}
+ // Returns true if `struct_def` needs a copy constructor and assignment
+ // operator because it has one or more table members, struct members with a
+ // custom cpp_type and non-naked pointer type, or vector members of those.
+ bool NeedsCopyCtorAssignOp(const StructDef &struct_def) {
+ for (const auto &field : struct_def.fields.vec) {
+ const auto &type = field->value.type;
+ if (field->deprecated) continue;
+ if (type.base_type == BASE_TYPE_STRUCT) {
+ const auto cpp_type = field->attributes.Lookup("cpp_type");
+ const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
+ const bool is_ptr = !(IsStruct(type) && field->native_inline) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
+ if (is_ptr) { return true; }
+ } else if (IsVector(type)) {
+ const auto vec_type = type.VectorType();
+ if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
+ const auto cpp_type = field->attributes.Lookup("cpp_type");
+ const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
+ const bool is_ptr = IsVectorOfPointers(*field) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
+ if (is_ptr) { return true; }
+ }
+ }
+ return false;
+ }
+
// 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; }
+ // In >= C++11, default member initializers are generated. To allow for
+ // aggregate initialization, do not emit a default constructor at all, with
+ // the exception of types that need a copy/move ctors and assignment
+ // operators.
+ if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
+ if (NeedsCopyCtorAssignOp(struct_def)) {
+ code_ += " {{NATIVE_NAME}}() = default;";
+ }
+ return;
+ }
std::string initializer_list;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@@ -1769,7 +1969,7 @@ class CppGenerator : public BaseGenerator {
Name(field) + "(" + native_default->constant + ")";
}
}
- } else if (cpp_type && field.value.type.base_type != BASE_TYPE_VECTOR) {
+ } else if (cpp_type && !IsVector(field.value.type)) {
if (!initializer_list.empty()) { initializer_list += ",\n "; }
initializer_list += Name(field) + "(0)";
}
@@ -1785,19 +1985,169 @@ class CppGenerator : public BaseGenerator {
code_ += " }";
}
+ // Generate the >= C++11 copy/move constructor and assignment operator
+ // declarations if required. Tables that are default-copyable do not get
+ // user-provided copy/move constructors and assignment operators so they
+ // remain aggregates.
+ void GenCopyMoveCtorAndAssigOpDecls(const StructDef &struct_def) {
+ if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
+ if (!NeedsCopyCtorAssignOp(struct_def)) return;
+ code_.SetValue("NATIVE_NAME",
+ NativeName(Name(struct_def), &struct_def, opts_));
+ code_ += " {{NATIVE_NAME}}(const {{NATIVE_NAME}} &o);";
+ code_ +=
+ " {{NATIVE_NAME}}({{NATIVE_NAME}}&&) FLATBUFFERS_NOEXCEPT = "
+ "default;";
+ code_ +=
+ " {{NATIVE_NAME}} &operator=({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT;";
+ }
+
+ // Generate the >= C++11 copy constructor and assignment operator definitions.
+ void GenCopyCtorAssignOpDefs(const StructDef &struct_def) {
+ if (opts_.g_cpp_std < cpp::CPP_STD_11) return;
+ if (!NeedsCopyCtorAssignOp(struct_def)) return;
+ std::string initializer_list;
+ std::string vector_copies;
+ std::string swaps;
+ for (const auto &field : struct_def.fields.vec) {
+ const auto &type = field->value.type;
+ if (field->deprecated || type.base_type == BASE_TYPE_UTYPE) continue;
+ if (type.base_type == BASE_TYPE_STRUCT) {
+ if (!initializer_list.empty()) { initializer_list += ",\n "; }
+ const auto cpp_type = field->attributes.Lookup("cpp_type");
+ const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
+ const std::string &type_name =
+ (cpp_type) ? cpp_type->constant
+ : GenTypeNative(type, /*invector*/ false, *field,
+ /*forcopy*/ true);
+ const bool is_ptr = !(IsStruct(type) && field->native_inline) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
+ CodeWriter cw;
+ cw.SetValue("FIELD", Name(*field));
+ cw.SetValue("TYPE", type_name);
+ if (is_ptr) {
+ cw +=
+ "{{FIELD}}((o.{{FIELD}}) ? new {{TYPE}}(*o.{{FIELD}}) : "
+ "nullptr)\\";
+ initializer_list += cw.ToString();
+ } else {
+ cw += "{{FIELD}}(o.{{FIELD}})\\";
+ initializer_list += cw.ToString();
+ }
+ } else if (IsVector(type)) {
+ const auto vec_type = type.VectorType();
+ if (vec_type.base_type == BASE_TYPE_UTYPE) continue;
+ const auto cpp_type = field->attributes.Lookup("cpp_type");
+ const auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
+ const std::string &type_name =
+ (cpp_type) ? cpp_type->constant
+ : GenTypeNative(vec_type, /*invector*/ true, *field,
+ /*forcopy*/ true);
+ const bool is_ptr = IsVectorOfPointers(*field) ||
+ (cpp_type && cpp_ptr_type->constant != "naked");
+ CodeWriter cw(" ");
+ cw.SetValue("FIELD", Name(*field));
+ cw.SetValue("TYPE", type_name);
+ if (is_ptr) {
+ // Use emplace_back to construct the potentially-smart pointer element
+ // from a raw pointer to a new-allocated copy.
+ cw.IncrementIdentLevel();
+ cw += "{{FIELD}}.reserve(o.{{FIELD}}.size());";
+ cw +=
+ "for (const auto &{{FIELD}}_ : o.{{FIELD}}) { "
+ "{{FIELD}}.emplace_back(({{FIELD}}_) ? new {{TYPE}}(*{{FIELD}}_) "
+ ": nullptr); }";
+ vector_copies += cw.ToString();
+ } else {
+ // For non-pointer elements, use std::vector's copy constructor in the
+ // initializer list. This will yield better performance than an insert
+ // range loop for trivially-copyable element types.
+ if (!initializer_list.empty()) { initializer_list += ",\n "; }
+ cw += "{{FIELD}}(o.{{FIELD}})\\";
+ initializer_list += cw.ToString();
+ }
+ } else {
+ if (!initializer_list.empty()) { initializer_list += ",\n "; }
+ CodeWriter cw;
+ cw.SetValue("FIELD", Name(*field));
+ cw += "{{FIELD}}(o.{{FIELD}})\\";
+ initializer_list += cw.ToString();
+ }
+ {
+ if (!swaps.empty()) { swaps += "\n "; }
+ CodeWriter cw;
+ cw.SetValue("FIELD", Name(*field));
+ cw += "std::swap({{FIELD}}, o.{{FIELD}});\\";
+ swaps += cw.ToString();
+ }
+ }
+ if (!initializer_list.empty()) {
+ initializer_list = "\n : " + initializer_list;
+ }
+ if (!swaps.empty()) { swaps = " " + swaps; }
+
+ code_.SetValue("NATIVE_NAME",
+ NativeName(Name(struct_def), &struct_def, opts_));
+ code_.SetValue("INIT_LIST", initializer_list);
+ code_.SetValue("VEC_COPY", vector_copies);
+ code_.SetValue("SWAPS", swaps);
+
+ code_ +=
+ "inline {{NATIVE_NAME}}::{{NATIVE_NAME}}(const {{NATIVE_NAME}} &o)"
+ "{{INIT_LIST}} {";
+ code_ += "{{VEC_COPY}}}\n";
+ code_ +=
+ "inline {{NATIVE_NAME}} &{{NATIVE_NAME}}::operator="
+ "({{NATIVE_NAME}} o) FLATBUFFERS_NOEXCEPT {";
+ code_ += "{{SWAPS}}";
+ code_ += " return *this;\n}\n";
+ }
+
void GenCompareOperator(const StructDef &struct_def,
- std::string accessSuffix = "") {
+ const 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;
+ const auto accessor = Name(field) + accessSuffix;
+ const auto lhs_accessor = "lhs." + accessor;
+ const auto rhs_accessor = "rhs." + accessor;
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 ||
+ (!IsVector(field.value.type) ||
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 + ")";
+ if (struct_def.fixed || field.native_inline ||
+ field.value.type.base_type != BASE_TYPE_STRUCT) {
+ // If the field is a vector of tables, the table need to be compared
+ // by value, instead of by the default unique_ptr == operator which
+ // compares by address.
+ if (IsVectorOfPointers(field)) {
+ const auto type =
+ GenTypeNative(field.value.type.VectorType(), true, field);
+ const auto equal_length =
+ lhs_accessor + ".size() == " + rhs_accessor + ".size()";
+ const auto elements_equal =
+ "std::equal(" + lhs_accessor + ".cbegin(), " + lhs_accessor +
+ ".cend(), " + rhs_accessor + ".cbegin(), [](" + type +
+ " const &a, " + type +
+ " const &b) { return (a == b) || (a && b && *a == *b); })";
+
+ compare_op += "(" + equal_length + " && " + elements_equal + ")";
+ } else if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ compare_op += "(*" + lhs_accessor + " == *" + rhs_accessor + ")";
+ } else {
+ compare_op += "(" + lhs_accessor + " == " + rhs_accessor + ")";
+ }
+ } else {
+ // Deep compare of std::unique_ptr. Null is not equal to empty.
+ std::string both_null =
+ "(" + lhs_accessor + " == " + rhs_accessor + ")";
+ std::string not_null_and_equal = "(lhs." + accessor + " && rhs." +
+ accessor + " && *lhs." + accessor +
+ " == *rhs." + accessor + ")";
+ compare_op += "(" + both_null + " || " + not_null_and_equal + ")";
+ }
}
}
@@ -1853,20 +2203,36 @@ class CppGenerator : public BaseGenerator {
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_ += "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);
- }
+ for (const auto field : struct_def.fields.vec) { GenMember(*field); }
GenOperatorNewDelete(struct_def);
GenDefaultConstructor(struct_def);
+ GenCopyMoveCtorAndAssigOpDecls(struct_def);
code_ += "};";
- if (opts_.gen_compare) GenCompareOperator(struct_def);
code_ += "";
}
+ // Adds a typedef to the binary schema type so one could get the bfbs based
+ // on the type at runtime.
+ void GenBinarySchemaTypeDef(const StructDef *struct_def) {
+ if (struct_def && opts_.binary_schema_gen_embed) {
+ code_ += " typedef " + WrapInNameSpace(*struct_def) +
+ "BinarySchema BinarySchema;";
+ }
+ }
+
+ void GenNativeTablePost(const StructDef &struct_def) {
+ if (opts_.gen_compare) {
+ const auto native_name = NativeName(Name(struct_def), &struct_def, opts_);
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_.SetValue("NATIVE_NAME", native_name);
+ 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);
@@ -1875,10 +2241,15 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("SIZE", GenTypeSize(field.value.type));
code_.SetValue("OFFSET", GenFieldOffsetName(field));
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
+ code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
code_ +=
- "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
+ "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
+ "{{OFFSET}}, {{ALIGN}})\\";
} else {
- code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
+ code_.SetValue("OFFSET_SIZE", field.offset64 ? "64" : "");
+ code_ +=
+ "{{PRE}}VerifyOffset{{OFFSET_SIZE}}{{REQUIRED}}(verifier, "
+ "{{OFFSET}})\\";
}
switch (field.value.type.base_type) {
@@ -1900,6 +2271,7 @@ class CppGenerator : public BaseGenerator {
code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\";
break;
}
+ case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\";
@@ -1923,6 +2295,19 @@ class CppGenerator : public BaseGenerator {
}
default: break;
}
+
+ auto nfn = GetNestedFlatBufferName(field);
+ if (!nfn.empty()) {
+ code_.SetValue("CPP_NAME", nfn);
+ // FIXME: file_identifier.
+ code_ +=
+ "{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>"
+ "({{NAME}}(), nullptr)\\";
+ } else if (field.flexbuffer) {
+ code_ +=
+ "{{PRE}}flexbuffers::VerifyNestedFlexBuffer"
+ "({{NAME}}(), verifier)\\";
+ }
break;
}
default: {
@@ -1931,24 +2316,153 @@ class CppGenerator : public BaseGenerator {
}
}
+ void GenComparatorForStruct(const StructDef &struct_def, size_t space_size,
+ const std::string lhs_struct_literal,
+ const std::string rhs_struct_literal) {
+ code_.SetValue("LHS_PREFIX", lhs_struct_literal);
+ code_.SetValue("RHS_PREFIX", rhs_struct_literal);
+ std::string space(space_size, ' ');
+ for (const auto &curr_field : struct_def.fields.vec) {
+ const auto curr_field_name = Name(*curr_field);
+ code_.SetValue("CURR_FIELD_NAME", curr_field_name);
+ code_.SetValue("LHS", lhs_struct_literal + "_" + curr_field_name);
+ code_.SetValue("RHS", rhs_struct_literal + "_" + curr_field_name);
+ const bool is_scalar = IsScalar(curr_field->value.type.base_type);
+ const bool is_array = IsArray(curr_field->value.type);
+ const bool is_struct = IsStruct(curr_field->value.type);
+
+ // If encouter a key field, call KeyCompareWithValue to compare this
+ // field.
+ if (curr_field->key) {
+ code_ += space +
+ "const auto {{RHS}} = {{RHS_PREFIX}}.{{CURR_FIELD_NAME}}();";
+ code_ += space +
+ "const auto {{CURR_FIELD_NAME}}_compare_result = "
+ "{{LHS_PREFIX}}.KeyCompareWithValue({{RHS}});";
+
+ code_ += space + "if ({{CURR_FIELD_NAME}}_compare_result != 0)";
+ code_ += space + " return {{CURR_FIELD_NAME}}_compare_result;";
+ continue;
+ }
+
+ code_ +=
+ space + "const auto {{LHS}} = {{LHS_PREFIX}}.{{CURR_FIELD_NAME}}();";
+ code_ +=
+ space + "const auto {{RHS}} = {{RHS_PREFIX}}.{{CURR_FIELD_NAME}}();";
+ if (is_scalar) {
+ code_ += space + "if ({{LHS}} != {{RHS}})";
+ code_ += space +
+ " return static_cast<int>({{LHS}} > {{RHS}}) - "
+ "static_cast<int>({{LHS}} < {{RHS}});";
+ } else if (is_array) {
+ const auto &elem_type = curr_field->value.type.VectorType();
+ code_ +=
+ space +
+ "for (::flatbuffers::uoffset_t i = 0; i < {{LHS}}->size(); i++) {";
+ code_ += space + " const auto {{LHS}}_elem = {{LHS}}->Get(i);";
+ code_ += space + " const auto {{RHS}}_elem = {{RHS}}->Get(i);";
+ if (IsScalar(elem_type.base_type)) {
+ code_ += space + " if ({{LHS}}_elem != {{RHS}}_elem)";
+ code_ += space +
+ " return static_cast<int>({{LHS}}_elem > {{RHS}}_elem) - "
+ "static_cast<int>({{LHS}}_elem < {{RHS}}_elem);";
+ code_ += space + "}";
+
+ } else if (IsStruct(elem_type)) {
+ if (curr_field->key) {
+ code_ += space +
+ "const auto {{CURR_FIELD_NAME}}_compare_result = "
+ "{{LHS_PREFIX}}.KeyCompareWithValue({{RHS}});";
+ code_ += space + "if ({{CURR_FIELD_NAME}}_compare_result != 0)";
+ code_ += space + " return {{CURR_FIELD_NAME}}_compare_result;";
+ continue;
+ }
+ GenComparatorForStruct(
+ *curr_field->value.type.struct_def, space_size + 2,
+ code_.GetValue("LHS") + "_elem", code_.GetValue("RHS") + "_elem");
+
+ code_ += space + "}";
+ }
+
+ } else if (is_struct) {
+ GenComparatorForStruct(*curr_field->value.type.struct_def, space_size,
+ code_.GetValue("LHS"), code_.GetValue("RHS"));
+ }
+ }
+ }
+
// 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 {";
+ const bool is_string = IsString(field.value.type);
+ const bool is_array = IsArray(field.value.type);
+ const bool is_struct = IsStruct(field.value.type);
+ // Generate KeyCompareLessThan function
+ code_ +=
+ " bool KeyCompareLessThan(const {{STRUCT_NAME}} * const o) const {";
if (is_string) {
- // use operator< of flatbuffers::String
+ // use operator< of ::flatbuffers::String
code_ += " return *{{FIELD_NAME}}() < *o->{{FIELD_NAME}}();";
+ } else if (is_array || is_struct) {
+ code_ += " return KeyCompareWithValue(o->{{FIELD_NAME}}()) < 0;";
} else {
code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
}
code_ += " }";
+ // Generate KeyCompareWithValue function
if (is_string) {
- code_ += " int KeyCompareWithValue(const char *val) const {";
- code_ += " return strcmp({{FIELD_NAME}}()->c_str(), val);";
- code_ += " }";
+ code_ += " int KeyCompareWithValue(const char *_{{FIELD_NAME}}) const {";
+ code_ += " return strcmp({{FIELD_NAME}}()->c_str(), _{{FIELD_NAME}});";
+ } else if (is_array) {
+ const auto &elem_type = field.value.type.VectorType();
+ std::string input_type = "::flatbuffers::Array<" +
+ GenTypeGet(elem_type, "", "", "", false) + ", " +
+ NumToString(elem_type.fixed_length) + ">";
+ code_.SetValue("INPUT_TYPE", input_type);
+ code_ +=
+ " int KeyCompareWithValue(const {{INPUT_TYPE}} *_{{FIELD_NAME}}"
+ ") const {";
+ code_ +=
+ " const {{INPUT_TYPE}} *curr_{{FIELD_NAME}} = {{FIELD_NAME}}();";
+ code_ +=
+ " for (::flatbuffers::uoffset_t i = 0; i < "
+ "curr_{{FIELD_NAME}}->size(); i++) {";
+
+ if (IsScalar(elem_type.base_type)) {
+ code_ += " const auto lhs = curr_{{FIELD_NAME}}->Get(i);";
+ code_ += " const auto rhs = _{{FIELD_NAME}}->Get(i);";
+ code_ += " if (lhs != rhs)";
+ code_ +=
+ " return static_cast<int>(lhs > rhs)"
+ " - static_cast<int>(lhs < rhs);";
+ } else if (IsStruct(elem_type)) {
+ code_ +=
+ " const auto &lhs_{{FIELD_NAME}} = "
+ "*(curr_{{FIELD_NAME}}->Get(i));";
+ code_ +=
+ " const auto &rhs_{{FIELD_NAME}} = "
+ "*(_{{FIELD_NAME}}->Get(i));";
+ GenComparatorForStruct(*elem_type.struct_def, 6,
+ "lhs_" + code_.GetValue("FIELD_NAME"),
+ "rhs_" + code_.GetValue("FIELD_NAME"));
+ }
+ code_ += " }";
+ code_ += " return 0;";
+ } else if (is_struct) {
+ const auto *struct_def = field.value.type.struct_def;
+ code_.SetValue("INPUT_TYPE",
+ GenTypeGet(field.value.type, "", "", "", false));
+ code_ +=
+ " int KeyCompareWithValue(const {{INPUT_TYPE}} &_{{FIELD_NAME}}) "
+ "const {";
+ code_ += " const auto &lhs_{{FIELD_NAME}} = {{FIELD_NAME}}();";
+ code_ += " const auto &rhs_{{FIELD_NAME}} = _{{FIELD_NAME}};";
+ GenComparatorForStruct(*struct_def, 4,
+ "lhs_" + code_.GetValue("FIELD_NAME"),
+ "rhs_" + code_.GetValue("FIELD_NAME"));
+ code_ += " return 0;";
+
} else {
FLATBUFFERS_ASSERT(IsScalar(field.value.type.base_type));
auto type = GenTypeBasic(field.value.type, false);
@@ -1958,12 +2472,13 @@ class CppGenerator : public BaseGenerator {
}
// 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_ += " }";
+ " int KeyCompareWithValue({{KEY_TYPE}} _{{FIELD_NAME}}) const {";
+ code_ +=
+ " return static_cast<int>({{FIELD_NAME}}() > _{{FIELD_NAME}}) - "
+ "static_cast<int>({{FIELD_NAME}}() < _{{FIELD_NAME}});";
}
+ code_ += " }";
}
void GenTableUnionAsGetters(const FieldDef &field) {
@@ -1982,7 +2497,7 @@ class CppGenerator : public BaseGenerator {
// @TODO: Mby make this decisions more universal? How?
code_.SetValue("U_GET_TYPE",
- EscapeKeyword(field.name + UnionTypeFieldSuffix()));
+ EscapeKeyword(Name(field) + UnionTypeFieldSuffix()));
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(u->defined_namespace,
GetEnumValUse(*u, ev)));
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
@@ -2005,15 +2520,21 @@ class CppGenerator : public BaseGenerator {
GenComment(field.doc_comment, " ");
// Call a different accessor for pointers, that indirects.
- if (false == field.IsScalarOptional()) {
+ if (!field.IsScalarOptional()) {
const bool is_scalar = IsScalar(type.base_type);
std::string accessor;
- if (is_scalar)
+ std::string offset_size = "";
+ if (is_scalar) {
accessor = "GetField<";
- else if (IsStruct(type))
+ } else if (IsStruct(type)) {
accessor = "GetStruct<";
- else
- accessor = "GetPointer<";
+ } else {
+ if (field.offset64) {
+ accessor = "GetPointer64<";
+ } 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.
@@ -2080,14 +2601,12 @@ class CppGenerator : public BaseGenerator {
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) {
+ for (const auto &field : struct_def.fields.vec) {
+ if (field->deprecated) {
// Deprecated fields won't be accessible.
continue;
}
- code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_NAME", Name(*field));
code_.SetValue("FIELD_INDEX",
std::to_string(static_cast<long long>(index++)));
if (need_else) {
@@ -2112,14 +2631,8 @@ class CppGenerator : public BaseGenerator {
// };
//
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 = {\\";
+ code_ += "const char *, fields_number> field_names = {\\";
if (struct_def.fields.vec.empty()) {
code_ += "};";
return;
@@ -2134,14 +2647,14 @@ class CppGenerator : public BaseGenerator {
continue;
}
code_.SetValue("FIELD_NAME", Name(field));
- code_ += " \"{{FIELD_NAME}}\"\\";
+ code_ += R"( "{{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(
+ const 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(
@@ -2165,9 +2678,9 @@ class CppGenerator : public BaseGenerator {
code_ +=
" static constexpr auto fully_qualified_name = "
"\"{{FULLY_QUALIFIED_NAME}}\";";
+ GenFieldsNumber(struct_def);
GenFieldNames(struct_def);
GenFieldTypeHelper(struct_def);
- GenFieldsNumber(struct_def);
}
code_ += "};";
code_ += "";
@@ -2181,29 +2694,43 @@ class CppGenerator : public BaseGenerator {
auto offset_str = GenFieldOffsetName(field);
if (is_scalar) {
- const auto wire_type = GenTypeWire(type, "", false);
+ const auto wire_type = GenTypeWire(type, "", false, field.offset64);
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_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} _{{FIELD_NAME}}\\";
+ if (!field.IsScalarOptional()) {
code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field));
+ code_.SetValue(
+ "INTERFACE_DEFAULT_VALUE",
+ GenUnderlyingCast(field, true, GenDefaultConstant(field)));
+
+ // GenUnderlyingCast for a bool field generates 0 != 0
+ // So the type has to be checked and the appropriate default chosen
+ if (IsBool(field.value.type.base_type)) {
+ code_ += " = {{DEFAULT_VALUE}}) {";
+ } else {
+ code_ += " = {{INTERFACE_DEFAULT_VALUE}}) {";
+ }
code_ +=
" return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, "
"{{DEFAULT_VALUE}});";
} else {
+ code_ += ") {";
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<";
+ const std::string accessor = [&]() {
+ if (IsStruct(type)) { return "GetStruct<"; }
+ if (field.offset64) { return "GetPointer64<"; }
+ return "GetPointer<";
+ }();
auto underlying = accessor + wire_type + ">(" + offset_str + ")";
code_.SetValue("FIELD_TYPE", wire_type);
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying));
@@ -2214,6 +2741,21 @@ class CppGenerator : public BaseGenerator {
}
}
+ std::string GetNestedFlatBufferName(const FieldDef &field) {
+ auto nested = field.attributes.Lookup("nested_flatbuffer");
+ if (!nested) return "";
+ 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;
+ return TranslateNameSpace(qualified_name);
+ }
+
// 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); }
@@ -2225,15 +2767,17 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", Name(struct_def));
code_ +=
"struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
- " : private flatbuffers::Table {";
+ " : private ::flatbuffers::Table {";
if (opts_.generate_object_based_api) {
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
}
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
+ GenBinarySchemaTypeDef(parser_.root_struct_def_);
+
if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += " struct Traits;"; }
if (opts_.mini_reflect != IDLOptions::kNone) {
code_ +=
- " static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
+ " static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {";
code_ += " return {{STRUCT_NAME}}TypeTable();";
code_ += " }";
}
@@ -2241,22 +2785,20 @@ class CppGenerator : public BaseGenerator {
GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
// Generate field id constants.
- if (struct_def.fields.vec.size() > 0) {
+ if (!struct_def.fields.vec.empty()) {
// 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) {
+ for (const auto &field : struct_def.fields.vec) {
+ 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_.SetValue("OFFSET_NAME", GenFieldOffsetName(*field));
+ code_.SetValue("OFFSET_VALUE", NumToString(field->value.offset));
code_ += "{{SEP}} {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\";
code_.SetValue("SEP", ",\n");
}
@@ -2265,65 +2807,52 @@ class CppGenerator : public BaseGenerator {
}
// 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) {
+ for (const auto &field : struct_def.fields.vec) {
+ 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_.SetValue("FIELD_NAME", Name(*field));
+ GenTableFieldGetter(*field);
+ if (opts_.mutable_buffer) { GenTableFieldSetter(*field); }
+ auto nfn = GetNestedFlatBufferName(*field);
+ if (!nfn.empty()) {
+ code_.SetValue("CPP_NAME", nfn);
code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
+ code_ += " const auto _f = {{FIELD_NAME}}();";
code_ +=
- " return "
- "flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
+ " return _f ? ::flatbuffers::GetRoot<{{CPP_NAME}}>(_f->Data())";
+ code_ += " : nullptr;";
code_ += " }";
}
- if (field.flexbuffer) {
+ 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_ += " const auto _f = {{FIELD_NAME}}();";
+ code_ += " return _f ? flexbuffers::GetRoot(_f->Data(), _f->size())";
+ code_ += " : flexbuffers::Reference();";
code_ += " }";
}
// Generate a comparison function for this field if it is a key.
- if (field.key) { GenKeyFieldMethods(field); }
+ 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_ += " 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 ");
+ for (const auto &field : struct_def.fields.vec) {
+ if (field->deprecated) { continue; }
+ GenVerifyCall(*field, " &&\n ");
}
code_ += " &&\n verifier.EndTable();";
@@ -2340,17 +2869,15 @@ class CppGenerator : public BaseGenerator {
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) {
+ for (const auto &field : struct_def.fields.vec) {
+ if (field->deprecated || field->value.type.base_type != BASE_TYPE_UNION) {
continue;
}
- auto u = field.value.type.enum_def;
+ auto u = field->value.type.enum_def;
if (u->uses_multiple_type_instances) continue;
- code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_NAME", Name(*field));
for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
auto &ev = **u_it;
@@ -2363,7 +2890,7 @@ class CppGenerator : public BaseGenerator {
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));
+ code_.SetValue("U_FIELD_NAME", Name(*field) + "_as_" + Name(ev));
// `template<> const T *union_name_as<T>() const` accessor.
code_ +=
@@ -2397,8 +2924,9 @@ class CppGenerator : public BaseGenerator {
// 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);
+ const std::string &type =
+ IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
+ : GenTypeWire(vtype, "", false, field.offset64);
return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
"), " + std::to_string(static_cast<long long>(align)) + ");";
}
@@ -2411,8 +2939,8 @@ class CppGenerator : public BaseGenerator {
// Generate a builder struct:
code_ += "struct {{STRUCT_NAME}}Builder {";
code_ += " typedef {{STRUCT_NAME}} Table;";
- code_ += " flatbuffers::FlatBufferBuilder &fbb_;";
- code_ += " flatbuffers::uoffset_t start_;";
+ code_ += " " + GetBuilder() + " &fbb_;";
+ code_ += " ::flatbuffers::uoffset_t start_;";
bool has_string_or_vector_fields = false;
for (auto it = struct_def.fields.vec.begin();
@@ -2434,12 +2962,14 @@ class CppGenerator : public BaseGenerator {
// fbb_.AddElement<type>(offset, name, default);
// }
code_.SetValue("FIELD_NAME", Name(field));
- code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
+ code_.SetValue("FIELD_TYPE",
+ GenTypeWire(field.value.type, " ", true, field.offset64));
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);
+ const auto type =
+ GenTypeWire(field.value.type, "", false, field.offset64);
code_.SetValue("ADD_FN", "AddElement<" + type + ">");
} else if (IsStruct(field.value.type)) {
code_.SetValue("ADD_FN", "AddStruct");
@@ -2458,24 +2988,22 @@ class CppGenerator : public BaseGenerator {
}
// Builder constructor
- code_ +=
- " explicit {{STRUCT_NAME}}Builder(flatbuffers::FlatBufferBuilder "
- "&_fbb)";
+ code_ += " explicit {{STRUCT_NAME}}Builder(" + GetBuilder() +
+ " "
+ "&_fbb)";
code_ += " : fbb_(_fbb) {";
code_ += " start_ = fbb_.StartTable();";
code_ += " }";
// Finish() function.
- code_ += " flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
+ code_ += " ::flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
code_ += " const auto end = fbb_.EndTable(start_);";
- code_ += " auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
+ 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));
+ for (const auto &field : struct_def.fields.vec) {
+ 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}});";
}
}
@@ -2487,13 +3015,11 @@ class CppGenerator : public BaseGenerator {
// Generate a convenient CreateX function that uses the above builder
// to create a table in one go.
code_ +=
- "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
+ "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_ += " " + GetBuilder() + " &_fbb\\";
+ for (const auto &field : struct_def.fields.vec) {
+ if (!field->deprecated) { GenParam(*field, false, ",\n "); }
}
code_ += ") {";
@@ -2527,71 +3053,96 @@ class CppGenerator : public BaseGenerator {
// 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}}> "
+ "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 "); }
+ code_ += " " + GetBuilder() + " &_fbb\\";
+ for (const auto &field : struct_def.fields.vec) {
+ 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");
+ // Offset64 bit fields need to be added to the buffer first, so here we
+ // loop over the fields in order of their offset size, followed by their
+ // definition order. Otherwise the emitted code might add a Offset
+ // followed by an Offset64 which would trigger an assertion.
+
+ // TODO(derekbailey): maybe optimize for the case where there is no
+ // 64offsets in the whole schema?
+ ForAllFieldsOrderedByOffset(struct_def, [&](const FieldDef *field) {
+ if (field->deprecated) { return; }
+ code_.SetValue("FIELD_NAME", Name(*field));
+ if (IsString(field->value.type)) {
+ if (!field->shared) {
+ code_.SetValue(
+ "CREATE_STRING",
+ "CreateString" + std::string(field->offset64
+ ? "<::flatbuffers::Offset64>"
+ : ""));
+ } 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 std::string type = WrapInNameSpace(*vtype.struct_def);
+ if (has_key) {
+ code_ += "_fbb.CreateVectorOfSortedStructs<" + type + ">\\";
} 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 + " }";
+ // If the field uses 64-bit addressing, create a 64-bit vector.
+ if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
+ code_ += "_fbb.CreateVectorOfStructs64\\";
+ } else {
+ code_ += "_fbb.CreateVectorOfStructs\\";
+ if (field->offset64) {
+ // This is normal 32-bit vector, with 64-bit addressing.
+ code_ += "64<::flatbuffers::Vector>\\";
+ } else {
+ code_ += "<" + type + ">\\";
+ }
+ }
}
- 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 if (has_key) {
+ const auto type = WrapInNameSpace(*vtype.struct_def);
+ code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
+ } else {
+ const auto type = GenTypeWire(
+ vtype, "", VectorElementUserFacing(vtype), field->offset64);
+
+ if (field->value.type.base_type == BASE_TYPE_VECTOR64) {
+ code_ += "_fbb.CreateVector64\\";
} else {
- const auto type =
- GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
- code_ += "_fbb.CreateVector<" + type + ">\\";
+ // If the field uses 64-bit addressing, create a 64-bit vector.
+ code_.SetValue("64OFFSET", field->offset64 ? "64" : "");
+ code_.SetValue("TYPE",
+ field->offset64 ? "::flatbuffers::Vector" : type);
+
+ code_ += "_fbb.CreateVector{{64OFFSET}}<{{TYPE}}>\\";
}
- code_ +=
- has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
}
+ 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_ += "__\\";
- }
+ for (const auto &field : struct_def.fields.vec) {
+ if (field->deprecated) { continue; }
+ code_.SetValue("FIELD_NAME", Name(*field));
+ code_ += ",\n {{FIELD_NAME}}\\";
+ if (IsString(field->value.type) || IsVector(field->value.type)) {
+ code_ += "__\\";
}
}
code_ += ");";
@@ -2625,7 +3176,7 @@ class CppGenerator : public BaseGenerator {
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";
+ 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 + ")";
@@ -2638,7 +3189,8 @@ class CppGenerator : public BaseGenerator {
return ptype + "(new " + name + "(*" + val + "))";
}
} else {
- const auto ptype = GenTypeNativePtr(
+ std::string ptype = afield.native_inline ? "*" : "";
+ ptype += GenTypeNativePtr(
WrapNativeNameInNameSpace(*type.struct_def, opts_), &afield,
true);
return ptype + "(" + val + "->UnPack(_resolver))";
@@ -2661,12 +3213,14 @@ class CppGenerator : public BaseGenerator {
const FieldDef *union_field) {
std::string code;
switch (field.value.type.base_type) {
+ case BASE_TYPE_VECTOR64:
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()); ";
+ const std::string vector_field = "_o->" + name;
+ code += "{ " + vector_field + ".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.
@@ -2696,8 +3250,11 @@ class CppGenerator : public BaseGenerator {
? ".type"
: (field.value.type.element == BASE_TYPE_UNION ? ".value"
: "");
-
- code += "for (flatbuffers::uoffset_t _i = 0;";
+ if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
+ code += "for (::flatbuffers::uoffset64_t _i = 0;";
+ } else {
+ code += "for (::flatbuffers::uoffset_t _i = 0;";
+ }
code += " _i < _e->size(); _i++) { ";
auto cpp_type = field.attributes.Lookup("cpp_type");
if (cpp_type) {
@@ -2706,13 +3263,13 @@ class CppGenerator : public BaseGenerator {
// (*resolver)(&_o->field, (hash_value_t)(_e));
// else
// _o->field = nullptr;
- code += "//vector resolver, " + PtrType(&field) + "\n";
+ code += "/*vector resolver, " + PtrType(&field) + "*/ ";
code += "if (_resolver) ";
code += "(*_resolver)";
code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" +
access + "), ";
code +=
- "static_cast<flatbuffers::hash_value_t>(" + indexing + "));";
+ "static_cast<::flatbuffers::hash_value_t>(" + indexing + "));";
if (PtrType(&field) == "naked") {
code += " else ";
code += "_o->" + name + "[_i]" + access + " = nullptr";
@@ -2723,11 +3280,19 @@ class CppGenerator : public BaseGenerator {
code += "/* else do nothing */";
}
} else {
+ const bool is_pointer = IsVectorOfPointers(field);
+ if (is_pointer) {
+ code += "if(_o->" + name + "[_i]" + ") { ";
+ code += indexing + "->UnPackTo(_o->" + name +
+ "[_i].get(), _resolver);";
+ code += " } else { ";
+ }
code += "_o->" + name + "[_i]" + access + " = ";
code += GenUnpackVal(field.value.type.VectorType(), indexing, true,
field);
+ if (is_pointer) { code += "; }"; }
}
- code += "; } }";
+ code += "; } } else { " + vector_field + ".resize(0); }";
}
break;
}
@@ -2755,11 +3320,11 @@ class CppGenerator : public BaseGenerator {
// (*resolver)(&_o->field, (hash_value_t)(_e));
// else
// _o->field = nullptr;
- code += "//scalar resolver, " + PtrType(&field) + " \n";
+ code += "/*scalar resolver, " + PtrType(&field) + "*/ ";
code += "if (_resolver) ";
code += "(*_resolver)";
code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), ";
- code += "static_cast<flatbuffers::hash_value_t>(_e));";
+ code += "static_cast<::flatbuffers::hash_value_t>(_e));";
if (PtrType(&field) == "naked") {
code += " else ";
code += "_o->" + Name(field) + " = nullptr;";
@@ -2772,8 +3337,21 @@ class CppGenerator : public BaseGenerator {
} else {
// Generate code for assigning the value, of the form:
// _o->field = value;
- code += "_o->" + Name(field) + " = ";
+ const bool is_pointer = IsPointer(field);
+
+ const std::string out_field = "_o->" + Name(field);
+
+ if (is_pointer) {
+ code += "{ if(" + out_field + ") { ";
+ code += "_e->UnPackTo(" + out_field + ".get(), _resolver);";
+ code += " } else { ";
+ }
+ code += out_field + " = ";
code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
+ if (is_pointer) {
+ code += " } } else if (" + out_field + ") { " + out_field +
+ ".reset(); }";
+ }
}
break;
}
@@ -2789,8 +3367,7 @@ class CppGenerator : public BaseGenerator {
} else {
value += Name(field);
}
- if (field.value.type.base_type != BASE_TYPE_VECTOR &&
- field.attributes.Lookup("cpp_type")) {
+ if (!IsVector(field.value.type) && field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(field.value.type, false);
value =
"_rehasher ? "
@@ -2806,7 +3383,10 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateSharedString(_o->field)
case BASE_TYPE_STRING: {
if (!field.shared) {
- code += "_fbb.CreateString(";
+ code +=
+ "_fbb.CreateString" +
+ std::string(field.offset64 ? "<::flatbuffers::Offset64>" : "") +
+ "(";
} else {
code += "_fbb.CreateSharedString(";
}
@@ -2833,6 +3413,7 @@ class CppGenerator : public BaseGenerator {
// _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
// return CreateT(_fbb, _o->Get(i), rehasher);
// });
+ case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
auto vector_type = field.value.type.VectorType();
switch (vector_type.base_type) {
@@ -2843,7 +3424,8 @@ class CppGenerator : public BaseGenerator {
// Use by-function serialization to emulate
// CreateVectorOfStrings(); this works also with non-std strings.
code +=
- "_fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>"
+ "_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::"
+ "String>>"
" ";
code += "(" + value + ".size(), ";
code += "[](size_t i, _VectorArgs *__va) { ";
@@ -2866,22 +3448,35 @@ class CppGenerator : public BaseGenerator {
const auto pack_name =
struct_attrs.Lookup("native_type_pack_name");
if (pack_name) {
- code += ", flatbuffers::Pack" + pack_name->constant;
+ code += ", ::flatbuffers::Pack" + pack_name->constant;
}
code += ")";
} else {
- code += "_fbb.CreateVectorOfStructs";
+ // If the field uses 64-bit addressing, create a 64-bit vector.
+ if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
+ code += "_fbb.CreateVectorOfStructs64";
+ } else {
+ code += "_fbb.CreateVectorOfStructs";
+ if (field.offset64) {
+ // This is normal 32-bit vector, with 64-bit addressing.
+ code += "64<::flatbuffers::Vector>";
+ }
+ }
code += "(" + value + ")";
}
} else {
- code += "_fbb.CreateVector<flatbuffers::Offset<";
+ 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 )";
+ code += "(*__va->__fbb, ";
+ if (field.native_inline) {
+ code += "&(__va->_" + value + "[i])";
+ } else {
+ code += "__va->_" + value + "[i]" + GenPtrGet(field);
+ }
+ code += ", __va->__rehasher); }, &_va )";
}
break;
}
@@ -2891,7 +3486,7 @@ class CppGenerator : public BaseGenerator {
}
case BASE_TYPE_UNION: {
code +=
- "_fbb.CreateVector<flatbuffers::"
+ "_fbb.CreateVector<::flatbuffers::"
"Offset<void>>(" +
value +
".size(), [](size_t i, _VectorArgs *__va) { "
@@ -2901,10 +3496,16 @@ class CppGenerator : public BaseGenerator {
}
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)";
+ const std::string &type = opts_.scoped_enums
+ ? Name(*field.value.type.enum_def)
+ : "uint8_t";
+ auto enum_value = "__va->_" + value + "[i].type";
+ if (!opts_.scoped_enums)
+ enum_value = "static_cast<uint8_t>(" + enum_value + ")";
+
+ code += "_fbb.CreateVector<" + type + ">(" + value +
+ ".size(), [](size_t i, _VectorArgs *__va) { return " +
+ enum_value + "; }, &_va)";
break;
}
default: {
@@ -2915,7 +3516,7 @@ class CppGenerator : public BaseGenerator {
const auto basetype = GenTypeBasic(
field.value.type.enum_def->underlying_type, false);
code += "_fbb.CreateVectorScalarCast<" + basetype +
- ">(flatbuffers::data(" + value + "), " + value +
+ ">(::flatbuffers::data(" + value + "), " + value +
".size())";
} else if (field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(vector_type, false);
@@ -2926,7 +3527,17 @@ class CppGenerator : public BaseGenerator {
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
code += "; }, &_va )";
} else {
- code += "_fbb.CreateVector(" + value + ")";
+ // If the field uses 64-bit addressing, create a 64-bit vector.
+ if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
+ code += "_fbb.CreateVector64(" + value + ")";
+ } else {
+ code += "_fbb.CreateVector";
+ if (field.offset64) {
+ // This is normal 32-bit vector, with 64-bit addressing.
+ code += "64<::flatbuffers::Vector>";
+ }
+ code += "(" + value + ")";
+ }
}
break;
}
@@ -2935,7 +3546,8 @@ class CppGenerator : public BaseGenerator {
// 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()) {
+ if (field.attributes.Lookup("nested_flatbuffer") ||
+ (opts_.set_empty_vectors_to_null && !field.IsRequired())) {
code = value + ".size() ? " + code + " : 0";
}
break;
@@ -2950,7 +3562,7 @@ class CppGenerator : public BaseGenerator {
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";
+ code += "::flatbuffers::Pack";
const auto pack_name =
struct_attribs.Lookup("native_type_pack_name");
if (pack_name) { code += pack_name->constant; }
@@ -2958,14 +3570,15 @@ class CppGenerator : public BaseGenerator {
} else if (field.native_inline) {
code += "&" + value;
} else {
- code += value + " ? " + value + GenPtrGet(field) + " : 0";
+ code += value + " ? " + value + GenPtrGet(field) + " : nullptr";
}
} else {
// _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
- const auto type = field.value.type.struct_def->name;
+ const std::string &type = field.value.type.struct_def->name;
code += value + " ? Create" + type;
- code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)";
- code += " : 0";
+ code += "(_fbb, " + value;
+ if (!field.native_inline) code += GenPtrGet(field);
+ code += ", _rehasher) : 0";
}
break;
}
@@ -2979,11 +3592,16 @@ class CppGenerator : public BaseGenerator {
// Generate code for tables that needs to come after the regular definition.
void GenTablePost(const StructDef &struct_def) {
+ if (opts_.generate_object_based_api) { GenNativeTablePost(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 >= C++11 copy ctor and assignment operator definitions.
+ GenCopyCtorAssignOpDefs(struct_def);
+
// Generate the X::UnPack() method.
code_ +=
"inline " + TableUnPackSignature(struct_def, false, opts_) + " {";
@@ -3046,11 +3664,13 @@ class CppGenerator : public BaseGenerator {
code_ +=
" struct _VectorArgs "
- "{ flatbuffers::FlatBufferBuilder *__fbb; "
+ "{ " +
+ GetBuilder() +
+ " *__fbb; "
"const " +
NativeName(Name(struct_def), &struct_def, opts_) +
"* __o; "
- "const flatbuffers::rehasher_function_t *__rehasher; } _va = { "
+ "const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { "
"&_fbb, _o, _rehasher}; (void)_va;";
for (auto it = struct_def.fields.vec.begin();
@@ -3071,25 +3691,23 @@ class CppGenerator : public BaseGenerator {
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; }
+ for (const auto &field : struct_def.fields.vec) {
+ if (field->deprecated) { continue; }
bool pass_by_address = false;
- if (field.value.type.base_type == BASE_TYPE_STRUCT) {
- if (IsStruct(field.value.type)) {
+ 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");
+ 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) + "\\";
+ code_ += ",\n &_" + Name(*field) + "\\";
} else {
- code_ += ",\n _" + Name(field) + "\\";
+ code_ += ",\n _" + Name(*field) + "\\";
}
}
code_ += ");";
@@ -3134,10 +3752,8 @@ class CppGenerator : public BaseGenerator {
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 + "_";
+ for (const auto &field : struct_def.fields.vec) {
+ const auto field_name = Name(*field) + "_";
if (first_in_init_list) {
first_in_init_list = false;
@@ -3203,7 +3819,7 @@ class CppGenerator : public BaseGenerator {
init_list += Name(field) + "_";
if (IsScalar(type.base_type)) {
auto scalar_type = GenUnderlyingCast(field, false, arg_name);
- init_list += "(flatbuffers::EndianScalar(" + scalar_type + "))";
+ init_list += "(::flatbuffers::EndianScalar(" + scalar_type + "))";
} else {
FLATBUFFERS_ASSERT((is_array && !init_arrays) || IsStruct(type));
if (!is_array)
@@ -3226,10 +3842,8 @@ class CppGenerator : public BaseGenerator {
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;
+ for (const auto &field : struct_def.fields.vec) {
+ const auto &type = field->value.type;
if (IsArray(type) && init_arrays) {
const auto &element_type = type.VectorType();
const auto is_enum = IsEnum(element_type);
@@ -3239,14 +3853,14 @@ class CppGenerator : public BaseGenerator {
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 +
+ const auto field_name = Name(*field) + "_";
+ const auto arg_name = "_" + Name(*field);
+ code_ += " ::flatbuffers::" + get_array + "(" + field_name +
").CopyFromSpan(" + arg_name + ");";
}
- if (field.padding) {
+ if (field->padding) {
std::string padding;
- GenPadding(field, &padding, &padding_id, PaddingNoop);
+ GenPadding(*field, &padding, &padding_id, PaddingNoop);
code_ += padding;
}
}
@@ -3261,7 +3875,7 @@ class CppGenerator : public BaseGenerator {
// 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 + ", " +
+ std::string ret_type = "::flatbuffers::Array<" + face_type + ", " +
NumToString(type.fixed_length) + ">";
if (mutable_accessor)
code_ += " " + ret_type + " *mutable_{{FIELD_NAME}}() {";
@@ -3270,7 +3884,7 @@ class CppGenerator : public BaseGenerator {
std::string get_array =
is_enum ? "CastToArrayOfEnum<" + face_type + ">" : "CastToArray";
- code_ += " return &flatbuffers::" + get_array + "({{FIELD_VALUE}});";
+ code_ += " return &::flatbuffers::" + get_array + "({{FIELD_VALUE}});";
code_ += " }";
}
@@ -3291,21 +3905,19 @@ class CppGenerator : public BaseGenerator {
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;
+ for (const auto &field : struct_def.fields.vec) {
+ const auto &field_type = field->value.type;
code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
- code_.SetValue("FIELD_NAME", Name(field));
+ 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) {
+ if (field->padding) {
std::string padding;
- GenPadding(field, &padding, &padding_id, PaddingDefinition);
+ GenPadding(*field, &padding, &padding_id, PaddingDefinition);
code_ += padding;
}
}
@@ -3319,7 +3931,7 @@ class CppGenerator : public BaseGenerator {
// Make TypeTable accessible via the generated struct.
if (opts_.mini_reflect != IDLOptions::kNone) {
code_ +=
- " static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
+ " static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {";
code_ += " return {{STRUCT_NAME}}TypeTable();";
code_ += " }";
}
@@ -3333,35 +3945,31 @@ class CppGenerator : public BaseGenerator {
// 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);
- });
+ auto arrays_num = std::count_if(
+ struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
+ [](const 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;
+ // type name() const { return ::flatbuffers::EndianScalar(name_); }
+ for (const auto &field : struct_def.fields.vec) {
+ 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;
+ auto member = Name(*field) + "_";
+ const std::string &value =
+ is_scalar ? "::flatbuffers::EndianScalar(" + member + ")" : member;
- code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_NAME", Name(*field));
code_.SetValue("FIELD_TYPE", field_type);
- code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
+ code_.SetValue("FIELD_VALUE", GenUnderlyingCast(*field, true, value));
- GenComment(field.doc_comment, " ");
+ GenComment(field->doc_comment, " ");
// Generate a const accessor function.
if (is_array) {
@@ -3380,11 +3988,11 @@ class CppGenerator : public BaseGenerator {
if (is_scalar) {
code_.SetValue("ARG", GenTypeBasic(type, true));
code_.SetValue("FIELD_VALUE",
- GenUnderlyingCast(field, false, "_" + Name(field)));
+ GenUnderlyingCast(*field, false, "_" + Name(*field)));
code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {";
code_ +=
- " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
+ " ::flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
"{{FIELD_VALUE}});";
code_ += " }";
} else if (is_array) {
@@ -3397,7 +4005,7 @@ class CppGenerator : public BaseGenerator {
}
// Generate a comparison function for this field if it is a key.
- if (field.key) { GenKeyFieldMethods(field); }
+ if (field->key) { GenKeyFieldMethods(*field); }
}
code_.SetValue("NATIVE_NAME", Name(struct_def));
GenOperatorNewDelete(struct_def);
@@ -3463,7 +4071,7 @@ bool GenerateCPP(const Parser &parser, const std::string &path,
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::string 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;
@@ -3499,16 +4107,70 @@ bool GenerateCPP(const Parser &parser, const std::string &path,
std::string CPPMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
- const auto filebase =
- flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ const auto filebase = StripPath(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;
+ for (const std::string &included_file : included_files) {
+ make_rule += " " + included_file;
}
return make_rule;
}
+namespace {
+
+class CppCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateCPP(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ // Generate code from the provided `buffer` of given `length`. The buffer is a
+ // serialized reflection.fbs.
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = CPPMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateCppGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kCpp; }
+
+ std::string LanguageName() const override { return "C++"; }
+};
+
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewCppCodeGenerator() {
+ return std::unique_ptr<CppCodeGenerator>(new CppCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp.h b/contrib/libs/flatbuffers/src/idl_gen_cpp.h
new file mode 100644
index 0000000000..fcca063a8f
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_CPP_H_
+#define FLATBUFFERS_IDL_GEN_CPP_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Cpp code generator.
+std::unique_ptr<CodeGenerator> NewCppCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_CPP_H_
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
index 1ba2ef3e4a..c368428950 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
@@ -181,7 +181,7 @@ class CppIterGenerator : public BaseGenerator {
auto basename = flatbuffers::StripPath(noext);
code_ += "#include \"" + parser_.opts.include_prefix +
- (parser_.opts.keep_include_path ? noext : basename) +
+ (parser_.opts.keep_prefix ? noext : basename) +
".iter.fbs.h\"";
num_includes++;
}
@@ -488,7 +488,17 @@ class CppIterGenerator : public BaseGenerator {
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}})\\";
+ if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
+ code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
+ code_ +=
+ "{{PRE}}this->template VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, "
+ "{{OFFSET}}, {{ALIGN}})\\";
+ } else {
+ code_.SetValue("OFFSET_SIZE", field.offset64 ? "64" : "");
+ code_ +=
+ "{{PRE}}this->template VerifyOffset{{REQUIRED}}<{{SIZE}}>(verifier, "
+ "{{OFFSET}})\\";
+ }
switch (field.value.type.base_type) {
case BASE_TYPE_UNION: {
@@ -728,4 +738,55 @@ bool GenerateCPPYandexMapsIter(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace cpp_yandex_maps_iter {
+
+class CppIterCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateCPPYandexMapsIter(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kCppYandexMapsIter; }
+
+ std::string LanguageName() const override { return "C++Iter"; }
+};
+
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewCppYandexMapsIterCodeGenerator() {
+ return std::unique_ptr<cpp_yandex_maps_iter::CppIterCodeGenerator>(new cpp_yandex_maps_iter::CppIterCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.h b/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.h
new file mode 100644
index 0000000000..87b2449367
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.h
@@ -0,0 +1,13 @@
+#ifndef FLATBUFFERS_IDL_GEN_CPP_YANDEX_MAPS_ITER_H_
+#define FLATBUFFERS_IDL_GEN_CPP_YANDEX_MAPS_ITER_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Cpp Yandex Maps Iter code generator.
+std::unique_ptr<CodeGenerator> NewCppYandexMapsIterCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_CPP_YANDEX_MAPS_ITER_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
index 681ab6d642..0dbcd4b927 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
@@ -16,15 +16,15 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_csharp.h"
+
+#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 {
static TypedFloatConstantGenerator CSharpFloatGen("Double.", "Single.", "NaN",
@@ -46,8 +46,100 @@ class CSharpGenerator : public BaseGenerator {
public:
CSharpGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "cs"),
- cur_name_space_(nullptr) {}
+ : BaseGenerator(parser, path, file_name,
+ parser.opts.cs_global_alias ? "global::" : "", ".", "cs"),
+ cur_name_space_(nullptr) {
+ // clang-format off
+
+ // List of keywords retrieved from here:
+ // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
+
+ // One per line to ease comparisons to that list are easier
+
+ static const char *const keywords[] = {
+ "abstract",
+ "as",
+ "base",
+ "bool",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "checked",
+ "class",
+ "const",
+ "continue",
+ "decimal",
+ "default",
+ "delegate",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "event",
+ "explicit",
+ "extern",
+ "false",
+ "finally",
+ "fixed",
+ "float",
+ "for",
+ "foreach",
+ "goto",
+ "if",
+ "implicit",
+ "in",
+ "int",
+ "interface",
+ "internal",
+ "is",
+ "lock",
+ "long",
+ "namespace",
+ "new",
+ "null",
+ "object",
+ "operator",
+ "out",
+ "override",
+ "params",
+ "private",
+ "protected",
+ "public",
+ "readonly",
+ "ref",
+ "return",
+ "sbyte",
+ "sealed",
+ "short",
+ "sizeof",
+ "stackalloc",
+ "static",
+ "string",
+ "struct",
+ "switch",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typeof",
+ "uint",
+ "ulong",
+ "unchecked",
+ "unsafe",
+ "ushort",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "while",
+ nullptr,
+ // clang-format on
+ };
+
+ for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ }
CSharpGenerator &operator=(const CSharpGenerator &);
@@ -65,7 +157,7 @@ class CSharpGenerator : public BaseGenerator {
one_file_code += enumcode;
} else {
if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode,
- false))
+ false, parser_.opts))
return false;
}
}
@@ -77,26 +169,50 @@ class CSharpGenerator : public BaseGenerator {
if (!parser_.opts.one_file)
cur_name_space_ = struct_def.defined_namespace;
GenStruct(struct_def, &declcode, parser_.opts);
+ GenStructVerifier(struct_def, &declcode);
if (parser_.opts.one_file) {
one_file_code += declcode;
} else {
if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode,
- true))
+ true, parser_.opts))
return false;
}
}
if (parser_.opts.one_file) {
return SaveType(file_name_, *parser_.current_namespace_, one_file_code,
- true);
+ true, parser_.opts);
}
return true;
}
+ private:
+ std::unordered_set<std::string> keywords_;
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : "@" + name;
+ }
+
+ std::string Name(const FieldDef &field) const {
+ std::string name = ConvertCase(field.name, Case::kUpperCamel);
+ return EscapeKeyword(name);
+ }
+
+ std::string Name(const Definition &def) const {
+ return EscapeKeyword(def.name);
+ }
+
+ std::string NamespacedName(const Definition &def) const {
+ return WrapInNameSpace(def.defined_namespace, Name(def));
+ }
+
+ std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
+
// 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 {
+ const std::string &classcode, bool needs_includes,
+ const IDLOptions &options) const {
if (!classcode.length()) return true;
std::string code =
@@ -113,11 +229,14 @@ class CSharpGenerator : public BaseGenerator {
if (needs_includes) {
code += "using global::System;\n";
code += "using global::System.Collections.Generic;\n";
- code += "using global::FlatBuffers;\n\n";
+ code += "using global::Google.FlatBuffers;\n\n";
}
code += classcode;
if (!namespace_name.empty()) { code += "\n}\n"; }
- auto filename = NamespaceDir(ns) + defname + ".cs";
+ auto filename = NamespaceDir(ns) + defname;
+ if (options.one_file) { filename += options.filename_suffix; }
+ filename +=
+ options.filename_extension.empty() ? ".cs" : options.filename_extension;
return SaveFile(filename.c_str(), code, false);
}
@@ -134,9 +253,9 @@ class CSharpGenerator : public BaseGenerator {
// clang-format on
if (enableLangOverrides) {
- if (IsEnum(type)) return WrapInNameSpace(*type.enum_def);
+ if (IsEnum(type)) return NamespacedName(*type.enum_def);
if (type.base_type == BASE_TYPE_STRUCT) {
- return "Offset<" + WrapInNameSpace(*type.struct_def) + ">";
+ return "Offset<" + NamespacedName(*type.struct_def) + ">";
}
}
@@ -151,7 +270,7 @@ class CSharpGenerator : public BaseGenerator {
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_STRUCT: return NamespacedName(*type.struct_def);
case BASE_TYPE_UNION: return "TTable";
default: return "Table";
}
@@ -165,12 +284,12 @@ class CSharpGenerator : public BaseGenerator {
}
std::string GenOffsetType(const StructDef &struct_def) const {
- return "Offset<" + WrapInNameSpace(struct_def) + ">";
+ return "Offset<" + NamespacedName(struct_def) + ">";
}
std::string GenOffsetConstruct(const StructDef &struct_def,
const std::string &variable_name) const {
- return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name +
+ return "new Offset<" + NamespacedName(struct_def) + ">(" + variable_name +
")";
}
@@ -179,7 +298,7 @@ class CSharpGenerator : public BaseGenerator {
if (IsSeries(type)) {
return DestinationCast(type.VectorType());
} else {
- if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")";
+ if (IsEnum(type)) return "(" + NamespacedName(*type.enum_def) + ")";
}
return "";
}
@@ -190,17 +309,19 @@ class CSharpGenerator : public BaseGenerator {
// 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 {
+ std::string SourceCast(const Type &type,
+ const bool isOptional = false) const {
if (IsSeries(type)) {
return SourceCast(type.VectorType());
} else {
- if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")";
+ if (IsEnum(type))
+ return "(" + GenTypeBasic(type, false) + (isOptional ? "?" : "") + ")";
}
return "";
}
- std::string SourceCastBasic(const Type &type) const {
- return IsScalar(type.base_type) ? SourceCast(type) : "";
+ std::string SourceCastBasic(const Type &type, const bool isOptional) const {
+ return IsScalar(type.base_type) ? SourceCast(type, isOptional) : "";
}
std::string GenEnumDefaultValue(const FieldDef &field) const {
@@ -208,7 +329,7 @@ class CSharpGenerator : public BaseGenerator {
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)
+ return enum_val ? (NamespacedName(enum_def) + "." + Name(*enum_val))
: value.constant;
}
@@ -252,7 +373,7 @@ class CSharpGenerator : public BaseGenerator {
switch (value.type.base_type) {
case BASE_TYPE_STRING: return "default(StringOffset)";
case BASE_TYPE_STRUCT:
- return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) +
+ return "default(Offset<" + NamespacedName(*value.type.struct_def) +
">)";
case BASE_TYPE_VECTOR: return "default(VectorOffset)";
default: break;
@@ -293,14 +414,14 @@ class CSharpGenerator : public BaseGenerator {
} else {
code += "public ";
}
- code += "enum " + enum_def.name;
+ code += "enum " + Name(enum_def);
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 += Name(ev) + " = ";
code += enum_def.ToString(ev);
code += ",\n";
}
@@ -334,27 +455,32 @@ class CSharpGenerator : public BaseGenerator {
if (type.base_type == BASE_TYPE_BOOL) {
getter = "0!=" + getter;
} else if (GenTypeBasic(type, false) != "byte") {
- getter += MakeCamel(GenTypeBasic(type, false));
+ getter += ConvertCase(GenTypeBasic(type, false), Case::kUpperCamel);
}
return getter;
}
}
}
+ std::string GetObjectConstructor(flatbuffers::StructDef &struct_def,
+ const std::string &data_buffer,
+ const std::string &offset) const {
+ // Use the generated type directly, to properly handle default values that
+ // might not be written to the buffer.
+ return "new " + Name(struct_def) + "().__assign(" + offset + ", " +
+ data_buffer + ")";
+ }
+
// Returns the function name that is able to read a value of the given type.
- std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
+ std::string GenGetterForLookupByKey(flatbuffers::StructDef &struct_def,
+ 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;
+ const std::string &offset) const {
+ // Use the generated type directly, to properly handle default values that
+ // might not be written to the buffer.
+ auto name = Name(*key_field);
+ if (name == struct_def.name) { name += "_"; }
+ return GetObjectConstructor(struct_def, data_buffer, offset) + "." + name;
}
// Direct mutation is only allowed for scalar fields.
@@ -364,7 +490,7 @@ class CSharpGenerator : public BaseGenerator {
std::string setter = "__p.bb.Put";
if (GenTypeBasic(type, false) != "byte" &&
type.base_type != BASE_TYPE_BOOL) {
- setter += MakeCamel(GenTypeBasic(type, false));
+ setter += ConvertCase(GenTypeBasic(type, false), Case::kUpperCamel);
}
return setter;
} else {
@@ -374,8 +500,9 @@ class CSharpGenerator : public BaseGenerator {
// 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");
+ return IsScalar(type.base_type)
+ ? ConvertCase(GenTypeBasic(type, false), Case::kUpperCamel)
+ : (IsStruct(type) ? "Struct" : "Offset");
}
// Recursively generate arguments for a constructor, to deal with nested
@@ -395,7 +522,8 @@ class CSharpGenerator : public BaseGenerator {
// 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);
+ (nameprefix + (EscapeKeyword(field.name) + "_")).c_str(),
+ array_cnt);
} else {
code += ", ";
code += GenTypeBasic(type);
@@ -407,7 +535,7 @@ class CSharpGenerator : public BaseGenerator {
}
code += " ";
code += nameprefix;
- code += MakeCamel(field.name, true);
+ code += Name(field);
}
}
}
@@ -454,7 +582,7 @@ class CSharpGenerator : public BaseGenerator {
code += indent + " builder.Put";
code += GenMethod(type) + "(";
code += SourceCast(type);
- auto argname = nameprefix + MakeCamel(field.name, true);
+ auto argname = nameprefix + Name(field);
code += argname;
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
if (array_cnt > 0) {
@@ -485,37 +613,182 @@ class CSharpGenerator : public BaseGenerator {
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";
+ std::string GenKeyGetter(flatbuffers::StructDef &struct_def,
+ flatbuffers::FieldDef *key_field) const {
+ // Get the getter for the key of the struct.
+ return GenGetterForLookupByKey(struct_def, key_field, "builder.DataBuffer",
+ "builder.DataBuffer.Length - o1.Value") +
+ ".CompareTo(" +
+ GenGetterForLookupByKey(struct_def, key_field, "builder.DataBuffer",
+ "builder.DataBuffer.Length - o2.Value") +
+ ")";
+ }
+
+ // Get the value of a table verification function start
+ void GetStartOfTableVerifier(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\n";
+ code += "static public class " + struct_def.name + "Verify\n";
+ code += "{\n";
+ code += " static public bool Verify";
+ code += "(Google.FlatBuffers.Verifier verifier, uint tablePos)\n";
+ code += " {\n";
+ code += " return verifier.VerifyTableStart(tablePos)\n";
+ }
+
+ // Get the value of a table verification function end
+ void GetEndOfTableVerifier(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += " && verifier.VerifyTableEnd(tablePos);\n";
+ code += " }\n";
+ code += "}\n";
+ }
+
+ std::string GetNestedFlatBufferName(const FieldDef &field) {
+ std::string name;
+ if (field.nested_flatbuffer) {
+ name = NamespacedName(*field.nested_flatbuffer);
+ } else {
+ name = "";
+ }
+ return name ;
+ }
+
+ // Generate the code to call the appropriate Verify function(s) for a field.
+ void GenVerifyCall(CodeWriter &code_, const FieldDef &field, const char *prefix) {
+ code_.SetValue("PRE", prefix);
+ code_.SetValue("NAME", ConvertCase(field.name, Case::kUpperCamel));
+ code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : "");
+ code_.SetValue("REQUIRED_FLAG", field.IsRequired() ? "true" : "false");
+ code_.SetValue("TYPE", GenTypeGet(field.value.type));
+ code_.SetValue("INLINESIZE", NumToString(InlineSize(field.value.type)));
+ code_.SetValue("OFFSET", NumToString(field.value.offset));
+
+ if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
+ code_.SetValue("ALIGN", NumToString(InlineAlignment(field.value.type)));
+ code_ +=
+ "{{PRE}} && verifier.VerifyField(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{INLINESIZE}} /*{{TYPE}}*/, {{ALIGN}}, {{REQUIRED_FLAG}})";
} else {
- auto get_val = GenGetterForLookupByKey(key_field, "bb");
- key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
+ // TODO - probably code below should go to this 'else' - code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
+ }
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_UNION: {
+ auto union_name = NamespacedName(*field.value.type.enum_def);
+ code_.SetValue("ENUM_NAME1", field.value.type.enum_def->name);
+ code_.SetValue("ENUM_NAME", union_name);
+ code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
+ // Caution: This construction assumes, that UNION type id element has been created just before union data and
+ // its offset precedes union. Such assumption is common in flatbuffer implementation
+ code_.SetValue("TYPE_ID_OFFSET", NumToString(field.value.offset - sizeof(voffset_t)));
+ code_ += "{{PRE}} && verifier.VerifyUnion(tablePos, {{TYPE_ID_OFFSET}}, "
+ "{{OFFSET}} /*{{NAME}}*/, {{ENUM_NAME}}Verify.Verify, {{REQUIRED_FLAG}})";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}} && verifier.VerifyTable(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, {{REQUIRED_FLAG}})";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}} && verifier.VerifyString(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}} && verifier.VerifyVectorOfStrings(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{REQUIRED_FLAG}})";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}} && verifier.VerifyVectorOfTables(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{TYPE}}Verify.Verify, {{REQUIRED_FLAG}})";
+ } else {
+ code_.SetValue(
+ "VECTOR_ELEM_INLINESIZE",
+ NumToString(InlineSize(field.value.type.VectorType())));
+ code_ +=
+ "{{PRE}} && "
+ "verifier.VerifyVectorOfData(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} "
+ "/*{{TYPE}}*/, {{REQUIRED_FLAG}})";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ // Vectors of unions are not yet supported for go
+ break;
+ }
+ default:
+ // Generate verifier for vector of data.
+ // It may be either nested flatbuffer of just vector of bytes
+ auto nfn = GetNestedFlatBufferName(field);
+ if (!nfn.empty()) {
+ code_.SetValue("CPP_NAME", nfn);
+ // FIXME: file_identifier.
+ code_ += "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{CPP_NAME}}Verify.Verify, {{REQUIRED_FLAG}})";
+ } else if (field.flexbuffer) {
+ code_ += "{{PRE}} && verifier.VerifyNestedBuffer(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, null, {{REQUIRED_FLAG}})";
+ } else {
+ code_.SetValue("VECTOR_ELEM_INLINESIZE", NumToString(InlineSize(field.value.type.VectorType())));
+ code_ +=
+ "{{PRE}} && verifier.VerifyVectorOfData(tablePos, "
+ "{{OFFSET}} /*{{NAME}}*/, {{VECTOR_ELEM_INLINESIZE}} /*{{TYPE}}*/, {{REQUIRED_FLAG}})";
+ }
+ break;
+ }
+
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableVerifier(const StructDef &struct_def, std::string *code_ptr) {
+ CodeWriter code_;
+
+ GetStartOfTableVerifier(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;
+
+ GenVerifyCall(code_, field, "");
}
- return key_getter;
+
+ *code_ptr += code_.ToString();
+
+ GetEndOfTableVerifier(code_ptr);
}
- 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 + ")";
+ // Generate struct or table methods.
+ void GenStructVerifier(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ // cur_name_space_ = struct_def.defined_namespace;
+
+ // Generate verifiers
+ if (struct_def.fixed) {
+ // Fixed size structures do not require table members
+ // verification - instead structure size is verified using VerifyField
} 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 + ")";
+ // Create table verification function
+ GenTableVerifier(struct_def, code_ptr);
}
- return key_getter;
}
void GenStruct(StructDef &struct_def, std::string *code_ptr,
@@ -549,11 +822,11 @@ class CSharpGenerator : public BaseGenerator {
code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n";
if (!struct_def.fixed) {
- // Generate verson check method.
+ // Generate version 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 += "FLATBUFFERS_23_5_9(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
@@ -583,8 +856,20 @@ class CSharpGenerator : public BaseGenerator {
code += parser_.file_identifier_;
code += "\"); }\n";
}
+
+ // Generate the Verify method that checks if a ByteBuffer is save to
+ // access
+ code += " public static ";
+ code += "bool Verify" + struct_def.name + "(ByteBuffer _bb) {";
+ code += "Google.FlatBuffers.Verifier verifier = new ";
+ code += "Google.FlatBuffers.Verifier(_bb); ";
+ code += "return verifier.VerifyBuffer(\"";
+ code += parser_.file_identifier_;
+ code += "\", false, " + struct_def.name + "Verify.Verify);";
+ 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) ";
@@ -618,7 +903,8 @@ class CSharpGenerator : public BaseGenerator {
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 field_name_camel = Name(field);
+ if (field_name_camel == struct_def.name) { field_name_camel += "_"; }
std::string method_start =
" public " + type_name_dest + optional + " " + field_name_camel;
std::string obj = "(new " + type_name + "())";
@@ -745,8 +1031,7 @@ class CSharpGenerator : public BaseGenerator {
HasUnionStringValue(*vectortype.enum_def)) {
code += member_suffix;
code += "}\n";
- code += " public string " + MakeCamel(field.name, true) +
- "AsString(int j)";
+ code += " public string " + Name(field) + "AsString(int j)";
code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
code += "(" + index + ") : null";
}
@@ -759,8 +1044,7 @@ class CSharpGenerator : public BaseGenerator {
if (HasUnionStringValue(*field.value.type.enum_def)) {
code += member_suffix;
code += "}\n";
- code += " public string " + MakeCamel(field.name, true) +
- "AsString()";
+ code += " public string " + Name(field) + "AsString()";
code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
code += "(o + __p.bb_pos) : null";
}
@@ -795,7 +1079,9 @@ class CSharpGenerator : public BaseGenerator {
code += member_suffix;
code += "}\n";
if (IsVector(field.value.type)) {
- code += " public int " + MakeCamel(field.name, true);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ code += " public int " + camel_name;
code += "Length";
code += " { get";
code += offset_prefix;
@@ -810,9 +1096,9 @@ class CSharpGenerator : public BaseGenerator {
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
auto &key_field = **kit;
if (key_field.key) {
- auto qualified_name = WrapInNameSpace(sd);
+ auto qualified_name = NamespacedName(sd);
code += " public " + qualified_name + "? ";
- code += MakeCamel(field.name, true) + "ByKey(";
+ code += Name(field) + "ByKey(";
code += GenTypeGet(key_field.value.type) + " key)";
code += offset_prefix;
code += qualified_name + ".__lookup_by_key(";
@@ -831,7 +1117,7 @@ class CSharpGenerator : public BaseGenerator {
code += "#if ENABLE_SPAN_T\n";
code += " public Span<" + GenTypeBasic(field.value.type.VectorType()) +
"> Get";
- code += MakeCamel(field.name, true);
+ code += Name(field);
code += "Bytes() { return ";
code += "__p.__vector_as_span<" +
GenTypeBasic(field.value.type.VectorType()) + ">(";
@@ -841,7 +1127,7 @@ class CSharpGenerator : public BaseGenerator {
code += "); }\n";
code += "#else\n";
code += " public ArraySegment<byte>? Get";
- code += MakeCamel(field.name, true);
+ code += Name(field);
code += "Bytes() { return ";
code += "__p.__vector_as_arraysegment(";
code += NumToString(field.value.offset);
@@ -852,7 +1138,7 @@ class CSharpGenerator : public BaseGenerator {
code += " public ";
code += GenTypeBasic(field.value.type.VectorType());
code += "[] Get";
- code += MakeCamel(field.name, true);
+ code += Name(field);
code += "Array() { ";
if (IsEnum(field.value.type.VectorType())) {
// Since __vector_as_array does not work for enum types,
@@ -881,9 +1167,9 @@ class CSharpGenerator : public BaseGenerator {
}
// generate object accessors if is nested_flatbuffer
if (field.nested_flatbuffer) {
- auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
+ auto nested_type_name = NamespacedName(*field.nested_flatbuffer);
auto nested_method_name =
- MakeCamel(field.name, true) + "As" + field.nested_flatbuffer->name;
+ Name(field) + "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 + "?)";
@@ -904,15 +1190,16 @@ class CSharpGenerator : public BaseGenerator {
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);
+ auto setter_parameter =
+ underlying_type.base_type == BASE_TYPE_BOOL
+ ? "(byte)(" + EscapeKeyword(field.name) + " ? 1 : 0)"
+ : EscapeKeyword(field.name);
+ auto mutator_prefix = "Mutate";
// 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 +
- ") { ";
+ GenTypeGet(underlying_type) + " " +
+ EscapeKeyword(field.name) + ") { ";
auto setter_index =
is_series
? "__p." +
@@ -926,7 +1213,7 @@ class CSharpGenerator : public BaseGenerator {
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_prefix + Name(field);
code += mutator_params;
if (struct_def.fixed) {
code += GenSetter(underlying_type) + "(" + setter_index + ", ";
@@ -942,9 +1229,10 @@ class CSharpGenerator : public BaseGenerator {
}
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) + ";";
+ auto vt_offset_constant =
+ " public static final int VT_" +
+ ConvertCase(field.name, Case::kScreamingSnake) + " = " +
+ NumToString(field.value.offset) + ";";
code += vt_offset_constant;
code += "\n";
@@ -1002,13 +1290,13 @@ class CSharpGenerator : public BaseGenerator {
field.value.type.struct_def->defined_namespace,
GenTypeName_ObjectAPI(field.value.type.struct_def->name, opts));
code += " ";
- code += field.name;
+ code += EscapeKeyword(field.name);
code += " = null";
} else {
code += GenTypeBasic(field.value.type);
if (field.IsScalarOptional()) { code += "?"; }
code += " ";
- code += field.name;
+ code += EscapeKeyword(field.name);
if (!IsScalar(field.value.type.base_type)) code += "Offset";
code += " = ";
@@ -1028,13 +1316,13 @@ class CSharpGenerator : public BaseGenerator {
size == SizeOf(field.value.type.base_type))) {
code += " " + struct_def.name + ".";
code += "Add";
- code += MakeCamel(field.name) + "(builder, ";
+ code += Name(field) + "(builder, ";
if (IsStruct(field.value.type) &&
opts.generate_object_based_api) {
code += GenTypePointer(field.value.type) + ".Pack(builder, " +
- field.name + ")";
+ EscapeKeyword(field.name) + ")";
} else {
- code += field.name;
+ code += EscapeKeyword(field.name);
if (!IsScalar(field.value.type.base_type)) code += "Offset";
}
@@ -1062,17 +1350,17 @@ class CSharpGenerator : public BaseGenerator {
if (field.deprecated) continue;
if (field.key) key_field = &field;
code += " public static void Add";
- code += MakeCamel(field.name);
+ code += Name(field);
code += "(FlatBufferBuilder builder, ";
code += GenTypeBasic(field.value.type);
- auto argname = MakeCamel(field.name, false);
+ auto argname = ConvertCase(field.name, Case::kLowerCamel);
if (!IsScalar(field.value.type.base_type)) argname += "Offset";
if (field.IsScalarOptional()) { code += "?"; }
- code += " " + argname + ") { builder.Add";
+ code += " " + EscapeKeyword(argname) + ") { builder.Add";
code += GenMethod(field.value.type) + "(";
code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
- code += SourceCastBasic(field.value.type);
- code += argname;
+ code += SourceCastBasic(field.value.type, field.IsScalarOptional());
+ code += EscapeKeyword(argname);
if (!IsScalar(field.value.type.base_type) &&
field.value.type.base_type != BASE_TYPE_UNION) {
code += ".Value";
@@ -1093,7 +1381,7 @@ class CSharpGenerator : public BaseGenerator {
field_has_create_set.insert(&field);
code += " public static VectorOffset ";
code += "Create";
- code += MakeCamel(field.name);
+ code += Name(field);
code += "Vector(FlatBufferBuilder builder, ";
code += GenTypeBasic(vector_type) + "[] data) ";
code += "{ builder.StartVector(";
@@ -1105,7 +1393,11 @@ class CSharpGenerator : public BaseGenerator {
code += "Add";
code += GenMethod(vector_type);
code += "(";
- code += SourceCastBasic(vector_type);
+ // At the moment there is no support of the type Vector with
+ // optional enum, e.g. if we have enum type SomeEnum there is no way
+ // to define `SomeEmum?[] enums` in FlatBuffer schema, so isOptional
+ // = false
+ code += SourceCastBasic(vector_type, false);
code += "data[i]";
if (vector_type.base_type == BASE_TYPE_STRUCT ||
IsString(vector_type))
@@ -1113,9 +1405,11 @@ class CSharpGenerator : public BaseGenerator {
code += "); return ";
code += "builder.EndVector(); }\n";
+ // add Create...VectorBlock() overloads for T[], ArraySegment<T> and
+ // IntPtr
code += " public static VectorOffset ";
code += "Create";
- code += MakeCamel(field.name);
+ code += Name(field);
code += "VectorBlock(FlatBufferBuilder builder, ";
code += GenTypeBasic(vector_type) + "[] data) ";
code += "{ builder.StartVector(";
@@ -1123,11 +1417,31 @@ class CSharpGenerator : public BaseGenerator {
code += ", data.Length, ";
code += NumToString(alignment);
code += "); builder.Add(data); return builder.EndVector(); }\n";
+
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += Name(field);
+ code += "VectorBlock(FlatBufferBuilder builder, ";
+ code += "ArraySegment<" + GenTypeBasic(vector_type) + "> data) ";
+ code += "{ builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", data.Count, ";
+ code += NumToString(alignment);
+ code += "); builder.Add(data); return builder.EndVector(); }\n";
+
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += Name(field);
+ code += "VectorBlock(FlatBufferBuilder builder, ";
+ code += "IntPtr dataPtr, int sizeInBytes) ";
+ code += "{ builder.StartVector(1, sizeInBytes, 1); ";
+ code += "builder.Add<" + GenTypeBasic(vector_type) +
+ ">(dataPtr, sizeInBytes); 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 += Name(field);
code += "Vector(FlatBufferBuilder builder, int numElems) ";
code += "{ builder.StartVector(";
code += NumToString(elem_size);
@@ -1170,14 +1484,17 @@ class CSharpGenerator : public BaseGenerator {
// because `key_field` is not set for struct
if (struct_def.has_key && !struct_def.fixed) {
FLATBUFFERS_ASSERT(key_field);
+ auto name = Name(*key_field);
+ if (name == struct_def.name) { name += "_"; }
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 += " Array.Sort(offsets,\n";
+ code += " (Offset<" + struct_def.name + "> o1, Offset<" +
+ struct_def.name + "> o2) =>\n";
+ code += " " + GenKeyGetter(struct_def, key_field);
code += ");\n";
code += " return builder.CreateVectorOfTables(offsets);\n }\n";
@@ -1186,16 +1503,19 @@ class CSharpGenerator : public BaseGenerator {
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 +=
+ " " + struct_def.name + " obj_ = new " + struct_def.name + "();\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 +=
+ " int tableOffset = Table.__indirect(vectorLocation + 4 * "
+ "(start + middle), bb);\n";
+
+ code += " obj_.__assign(tableOffset, bb);\n";
+ code += " int comp = obj_." + name + ".CompareTo(key);\n";
code += " if (comp > 0) {\n";
code += " span = middle;\n";
code += " } else if (comp < 0) {\n";
@@ -1203,9 +1523,7 @@ class CSharpGenerator : public BaseGenerator {
code += " start += middle;\n";
code += " span -= middle;\n";
code += " } else {\n";
- code += " return ";
- code += "new " + struct_def.name + "()";
- code += ".__assign(tableOffset, bb);\n";
+ code += " return obj_;\n";
code += " }\n }\n";
code += " return null;\n";
code += " }\n";
@@ -1215,7 +1533,7 @@ class CSharpGenerator : public BaseGenerator {
GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create,
field_has_create_set);
}
- code += "};\n\n";
+ code += "}\n\n";
if (opts.generate_object_based_api) {
GenStruct_ObjectAPI(struct_def, code_ptr, opts);
@@ -1280,6 +1598,67 @@ class CSharpGenerator : public BaseGenerator {
code += " }\n";
}
+ std::string GenUnionVerify(const Type &union_type) const {
+ if (union_type.enum_def) {
+ const auto &enum_def = *union_type.enum_def;
+
+ auto ret =
+ "\n\nstatic public class " + enum_def.name + "Verify\n";
+ ret += "{\n";
+ ret +=
+ " static public bool Verify(Google.FlatBuffers.Verifier verifier, "
+ "byte typeId, uint tablePos)\n";
+ ret += " {\n";
+ ret += " bool result = true;\n";
+
+ const auto union_enum_loop = [&]() {
+ ret += " switch((" + enum_def.name + ")typeId)\n";
+ ret += " {\n";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ ret += " case " + Name(enum_def) + "." + Name(ev) + ":\n";
+
+ if (IsString(ev.union_type)) {
+ ret +=
+ " result = verifier.VerifyUnionString(tablePos);\n";
+ ret += " break;";
+ } else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ if (! ev.union_type.struct_def->fixed) {
+ auto type = GenTypeGet(ev.union_type);
+ ret += " result = " + type + "Verify.Verify(verifier, tablePos);\n";
+ } else {
+ ret += " result = verifier.VerifyUnionData(tablePos, " +
+ NumToString(InlineSize(ev.union_type)) + ", " +
+ NumToString(InlineAlignment(ev.union_type)) +
+ ");\n";;
+ }
+ ret += " break;";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ ret += "\n";
+ }
+
+ ret += " default: result = true;\n";
+ ret += " break;\n";
+ ret += " }\n";
+ ret += " return result;\n";
+ };
+
+ union_enum_loop();
+ ret += " }\n";
+ ret += "}\n";
+ ret += "\n";
+
+ return ret;
+ }
+ FLATBUFFERS_ASSERT(0);
+ return "";
+ }
+
void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr,
const IDLOptions &opts) const {
auto &code = *code_ptr;
@@ -1291,45 +1670,59 @@ class CSharpGenerator : public BaseGenerator {
code += "public ";
}
auto union_name = enum_def.name + "Union";
+ auto class_member = std::string("Value");
+ if (class_member == enum_def.name) { class_member += "_"; };
code += "class " + union_name + " {\n";
// Type
code += " public " + enum_def.name + " Type { get; set; }\n";
// Value
- code += " public object Value { get; set; }\n";
+ code += " public object " + class_member + " { 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 += " this." + class_member + " = null;\n";
code += " }\n\n";
// As<T>
- code += " public T As<T>() where T : class { return this.Value as T; }\n";
- // As
+ code += " public T As<T>() where T : class { return this." + class_member +
+ " as T; }\n";
+ // As, From
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";
+ std::string accessibility =
+ (ev.union_type.base_type == BASE_TYPE_STRUCT &&
+ ev.union_type.struct_def->attributes.Lookup("private"))
+ ? "internal"
+ : "public";
+ // As
+ code += " " + accessibility + " " + type_name + " As" + ev.name +
+ "() { return this.As<" + type_name + ">(); }\n";
+ // From
+ auto lower_ev_name = ev.name;
+ std::transform(lower_ev_name.begin(), lower_ev_name.end(),
+ lower_ev_name.begin(), CharToLower);
+ code += " " + accessibility + " static " + union_name + " From" +
+ ev.name + "(" + type_name + " _" + lower_ev_name +
+ ") { return new " + union_name + "{ Type = " + Name(enum_def) +
+ "." + Name(ev) + ", " + class_member + " = _" + lower_ev_name +
+ " }; }\n";
}
code += "\n";
// Pack()
- code += " public static int Pack(FlatBuffers.FlatBufferBuilder builder, " +
- union_name + " _o) {\n";
+ code +=
+ " public static int Pack(Google.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 ";
+ code += " case " + Name(enum_def) + "." + Name(ev) + ": return ";
if (IsString(ev.union_type)) {
code += "builder.CreateString(_o.As" + ev.name + "()).Value;\n";
} else {
@@ -1341,6 +1734,9 @@ class CSharpGenerator : public BaseGenerator {
code += " }\n";
code += " }\n";
code += "}\n\n";
+
+ code += GenUnionVerify(enum_def.underlying_type);
+
// JsonConverter
if (opts.cs_gen_json_serializer) {
if (enum_def.attributes.Lookup("private")) {
@@ -1377,7 +1773,7 @@ class CSharpGenerator : public BaseGenerator {
" _o, "
"Newtonsoft.Json.JsonSerializer serializer) {\n";
code += " if (_o == null) return;\n";
- code += " serializer.Serialize(writer, _o.Value);\n";
+ code += " serializer.Serialize(writer, _o." + class_member + ");\n";
code += " }\n";
code +=
" public override object ReadJson(Newtonsoft.Json.JsonReader "
@@ -1414,8 +1810,8 @@ class CSharpGenerator : public BaseGenerator {
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 +
+ code += " case " + Name(enum_def) + "." + Name(ev) + ": _o." +
+ class_member + " = serializer.Deserialize<" + type_name +
">(reader); break;\n";
}
}
@@ -1433,9 +1829,12 @@ class CSharpGenerator : public BaseGenerator {
void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
const std::string &camel_name,
+ const std::string &camel_name_short,
bool is_vector) const {
auto &code = *code_ptr;
std::string varialbe_name = "_o." + camel_name;
+ std::string class_member = "Value";
+ if (class_member == enum_def.name) class_member += "_";
std::string type_suffix = "";
std::string func_suffix = "()";
std::string indent = " ";
@@ -1450,20 +1849,21 @@ class CSharpGenerator : public BaseGenerator {
} 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";
+ code += NamespacedName(enum_def) + "Union();\n";
+ code += indent + varialbe_name + ".Type = this." + camel_name_short +
+ "Type" + type_suffix + ";\n";
+ code += indent + "switch (this." + camel_name_short + "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 +
+ code += indent + " case " + NamespacedName(enum_def) + "." + ev.name +
":\n";
- code += indent + " " + varialbe_name + ".Value = this." + camel_name;
+ code += indent + " " + varialbe_name + "." + class_member +
+ " = this." + camel_name;
if (IsString(ev.union_type)) {
code += "AsString" + func_suffix + ";\n";
} else {
@@ -1499,7 +1899,9 @@ class CSharpGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = MakeCamel(field.name);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ auto camel_name_short = Name(field);
auto start = " _o." + camel_name + " = ";
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1515,11 +1917,10 @@ class CSharpGenerator : public BaseGenerator {
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()";
+ 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." +
@@ -1534,7 +1935,7 @@ class CSharpGenerator : public BaseGenerator {
code += " for (var _j = 0; _j < this." + camel_name +
"Length; ++_j) {\n";
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- camel_name, true);
+ camel_name, camel_name_short, true);
code += " }\n";
} else if (field.value.type.element != BASE_TYPE_UTYPE) {
auto fixed = field.value.type.struct_def == nullptr;
@@ -1555,7 +1956,7 @@ class CSharpGenerator : public BaseGenerator {
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
- camel_name, false);
+ camel_name, camel_name_short, false);
break;
}
default: {
@@ -1574,7 +1975,9 @@ class CSharpGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = MakeCamel(field.name);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ auto camel_name_short = Name(field);
// pre
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1628,12 +2031,12 @@ class CSharpGenerator : public BaseGenerator {
break;
case BASE_TYPE_UTYPE:
property_name = camel_name.substr(0, camel_name.size() - 4);
- array_type = WrapInNameSpace(*field.value.type.enum_def);
+ array_type = NamespacedName(*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) +
+ to_array = NamespacedName(*field.value.type.enum_def) +
"Union.Pack(builder, _o." + property_name + "[_j])";
break;
default: gen_for_loop = false; break;
@@ -1650,7 +2053,7 @@ class CSharpGenerator : public BaseGenerator {
code += " var " + array_name + " = _o." + property_name +
".ToArray();\n";
}
- code += " _" + field.name + " = Create" + camel_name +
+ code += " _" + field.name + " = Create" + camel_name_short +
"Vector(builder, " + array_name + ");\n";
code += " }\n";
} else {
@@ -1662,7 +2065,7 @@ class CSharpGenerator : public BaseGenerator {
camel_name + "[_j]);";
code += " var _" + field.name + " = default(VectorOffset);\n";
code += " if (_o." + camel_name + " != null) {\n";
- code += " Start" + camel_name + "Vector(builder, _o." +
+ code += " Start" + camel_name_short + "Vector(builder, _o." +
camel_name + ".Count);\n";
code += " for (var _j = _o." + camel_name +
".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n";
@@ -1688,7 +2091,7 @@ class CSharpGenerator : public BaseGenerator {
}
case BASE_TYPE_UNION: {
code += " var _" + field.name + "_type = _o." + camel_name +
- " == null ? " + WrapInNameSpace(*field.value.type.enum_def) +
+ " == null ? " + NamespacedName(*field.value.type.enum_def) +
".NONE : " + "_o." + camel_name + ".Type;\n";
code +=
" var _" + field.name + " = _o." + camel_name +
@@ -1707,7 +2110,8 @@ class CSharpGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = MakeCamel(field.name);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (struct_def.fixed) {
@@ -1761,7 +2165,7 @@ class CSharpGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto camel_name = MakeCamel(field.name);
+ auto camel_name = Name(field);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def->fixed) {
@@ -1857,7 +2261,7 @@ class CSharpGenerator : public BaseGenerator {
}
code += "] = _o";
for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
- code += "." + MakeCamel(array_lengths[i].name);
+ code += "." + ConvertCase(array_lengths[i].name, Case::kUpperCamel);
if (array_lengths[i].length <= 0) continue;
code += "[idx" + NumToString(j++) + "]";
}
@@ -1868,7 +2272,7 @@ class CSharpGenerator : public BaseGenerator {
} else {
code += "_o";
for (size_t i = 0; i < array_lengths.size(); ++i) {
- code += "." + MakeCamel(array_lengths[i].name);
+ code += "." + ConvertCase(array_lengths[i].name, Case::kUpperCamel);
}
code += ";";
}
@@ -1911,13 +2315,13 @@ class CSharpGenerator : public BaseGenerator {
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";
+ type_name = NamespacedName(*type.enum_def) + "Union";
}
break;
}
case BASE_TYPE_UNION: {
- type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ type_name = NamespacedName(*type.enum_def) + "Union";
break;
}
default: break;
@@ -1961,10 +2365,11 @@ class CSharpGenerator : public BaseGenerator {
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);
+ auto camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
if (opts.cs_gen_json_serializer) {
if (IsUnion(field.value.type)) {
- auto utype_name = WrapInNameSpace(*field.value.type.enum_def);
+ auto utype_name = NamespacedName(*field.value.type.enum_def);
code +=
" [Newtonsoft.Json.JsonProperty(\"" + field.name + "_type\")]\n";
if (IsVector(field.value.type)) {
@@ -2027,7 +2432,9 @@ class CSharpGenerator : public BaseGenerator {
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 camel_name = Name(field);
+ if (camel_name == struct_def.name) { camel_name += "_"; }
+ code += " this." + camel_name + " = ";
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
if (IsScalar(field.value.type.base_type)) {
code += GenDefaultValue(field) + ";\n";
@@ -2097,4 +2504,58 @@ bool GenerateCSharp(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace {
+
+class CSharpCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateCSharp(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = CSharpMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kCSharp; }
+
+ std::string LanguageName() const override { return "CSharp"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewCSharpCodeGenerator() {
+ return std::unique_ptr<CSharpCodeGenerator>(new CSharpCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_csharp.h b/contrib/libs/flatbuffers/src/idl_gen_csharp.h
new file mode 100644
index 0000000000..f5895a9369
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_csharp.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_CSHARP_H_
+#define FLATBUFFERS_IDL_GEN_CSHARP_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new CSharp code generator.
+std::unique_ptr<CodeGenerator> NewCSharpCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_CSHARP_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_dart.cpp b/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
index 56c4a82555..299409bac2 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
@@ -15,32 +15,66 @@
*/
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_dart.h"
+
#include <cassert>
+#include <cmath>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace dart {
+namespace {
+
+static Namer::Config DartDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kUnknown, // unused.
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kSnake2,
+ /*namespace_seperator=*/".",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"$",
+ /*keyword_suffix=*/"",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".dart" };
+}
+
+static std::set<std::string> DartKeywords() {
+ // see https://www.dartlang.org/guides/language/language-tour#keywords
+ // yield*, async*, and sync* shouldn't be proble
+ return {
+ "abstract", "else", "import", "show", "as", "enum",
+ "in", "static", "assert", "export", "interface", "super",
+ "async", "extends", "is", "switch", "await", "extension",
+ "late", "sync", "break", "external", "library", "this",
+ "case", "factory", "mixin", "throw", "catch", "false",
+ "new", "true", "class", "final", "null", "try",
+ "const", "finally", "on", "typedef", "continue", "for",
+ "operator", "var", "covariant", "Function", "part", "void",
+ "default", "get", "required", "while", "deferred", "hide",
+ "rethrow", "with", "do", "if", "return", "yield",
+ "dynamic", "implements", "set",
+ };
+}
+} // namespace
+
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.
@@ -50,20 +84,57 @@ class DartGenerator : public BaseGenerator {
DartGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "dart") {}
+ : BaseGenerator(parser, path, file_name, "", ".", "dart"),
+ namer_(WithFlagOptions(DartDefaultConfig(), parser.opts, path),
+ DartKeywords()) {}
+
+ template<typename T>
+ void import_generator(const std::vector<T *> &definitions,
+ const std::string &included,
+ std::set<std::string> &imports) {
+ for (const auto &item : definitions) {
+ if (item->file == included) {
+ std::string component = namer_.Namespace(*item->defined_namespace);
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(item->file));
+ std::string filename =
+ namer_.File(filebase + (component.empty() ? "" : "_" + component));
+
+ imports.emplace("import './" + filename + "'" +
+ (component.empty()
+ ? ";\n"
+ : " as " + ImportAliasName(component) + ";\n"));
+ }
+ }
+ }
+
// 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);
+ GenerateEnums(namespace_code);
+ GenerateStructs(namespace_code);
+
+ std::set<std::string> imports;
+
+ for (const auto &included_file : parser_.GetIncludedFiles()) {
+ if (included_file.filename == parser_.file_being_parsed_) continue;
+
+ import_generator(parser_.structs_.vec, included_file.filename, imports);
+ import_generator(parser_.enums_.vec, included_file.filename, imports);
+ }
+
+ std::string import_code = "";
+ for (const auto &file : imports) { import_code += file; }
+
+ import_code += import_code.empty() ? "" : "\n";
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, "
+ "// ignore_for_file: unused_import, unused_field, unused_element, "
"unused_local_variable\n\n";
if (!kv->first.empty()) { code += "library " + kv->first + ";\n\n"; }
@@ -75,31 +146,26 @@ class DartGenerator : public BaseGenerator {
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 += "import './" + Filename(kv2->first, /*path=*/false) +
+ "' as " + ImportAliasName(kv2->first) + ";\n";
}
}
+
code += "\n";
+ code += import_code;
+
code += kv->second;
- if (!SaveFile(
- GeneratedFileName(
- path_,
- file_name_ + (!kv->first.empty() ? "_" + kv->first : ""),
- parser_.opts)
- .c_str(),
- code, false)) {
- return false;
- }
+ if (!SaveFile(Filename(kv->first).c_str(), code, false)) { return false; }
}
return true;
}
+ std::string Filename(const std::string &suffix, bool path = true) const {
+ return (path ? path_ : "") +
+ namer_.File(file_name_ + (suffix.empty() ? "" : "_" + suffix));
+ }
+
private:
static std::string ImportAliasName(const std::string &ns) {
std::string ret;
@@ -113,62 +179,15 @@ class DartGenerator : public BaseGenerator {
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) {
+ 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);
+ GenEnum(enum_def, namespace_code);
}
}
- void GenerateStructs(namespace_code_map *namespace_code) {
+ void GenerateStructs(namespace_code_map &namespace_code) {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
@@ -178,70 +197,51 @@ class DartGenerator : public BaseGenerator {
// 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;
-
+ const char *indent, std::string &code) {
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) {
+ 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";
+ std::string &code =
+ namespace_code[namer_.Namespace(*enum_def.defined_namespace)];
+ GenDocComment(enum_def.doc_comment, "", code);
+
+ const std::string enum_type =
+ namer_.Type(enum_def) + (enum_def.is_union ? "TypeId" : "");
+ const bool is_bit_flags =
+ enum_def.attributes.Lookup("bit_flags") != nullptr;
+ // The flatbuffer schema language allows bit flag enums to potentially have
+ // a default value of zero, even if it's not a valid enum value...
+ const bool permit_zero = is_bit_flags;
+
+ code += "class " + enum_type + " {\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 += " const " + enum_type + "._(this.value);\n\n";
+ code += " factory " + enum_type + ".fromValue(int value) {\n";
+ code += " final result = values[value];\n";
+ code += " if (result == null) {\n";
+ if (permit_zero) {
+ code += " if (value == 0) {\n";
+ code += " return " + enum_type + "._(0);\n";
+ code += " } else {\n";
+ }
+ code += " throw StateError('Invalid value $value for bit flag enum ";
+ code += enum_type + "');\n";
+ if (permit_zero) { code += " }\n"; }
code += " }\n";
- code += " return values[value];\n";
+ code += " return result;\n";
code += " }\n\n";
+ code += " static " + enum_type + "? _createOrNull(int? value) => \n";
+ code +=
+ " value == null ? null : " + enum_type + ".fromValue(value);\n\n";
+
// this is meaningless for bit_flags
// however, note that unlike "regular" dart enums this enum can still have
// holes.
@@ -258,52 +258,52 @@ class DartGenerator : public BaseGenerator {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
+ const auto enum_var = namer_.Variant(ev);
if (!ev.doc_comment.empty()) {
if (it != enum_def.Vals().begin()) { code += '\n'; }
- GenDocComment(ev.doc_comment, &code, "", " ");
+ GenDocComment(ev.doc_comment, " ", code);
}
- code += " static const " + name + " " + ev.name + " = ";
- code += "const " + name + "._(" + enum_def.ToString(ev) + ");\n";
+ code += " static const " + enum_type + " " + enum_var + " = " +
+ enum_type + "._(" + enum_def.ToString(ev) + ");\n";
}
- code += " static const Map<int," + name + "> values = {";
+ code += " static const Map<int, " + enum_type + "> values = {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
- code += enum_def.ToString(ev) + ": " + ev.name + ",";
+ const auto enum_var = namer_.Variant(ev);
+ if (it != enum_def.Vals().begin()) code += ",\n";
+ code += " " + enum_def.ToString(ev) + ": " + enum_var;
}
code += "};\n\n";
- code += " static const " + _kFb + ".Reader<" + name +
- "> reader = const _" + name + "Reader();\n\n";
+ code += " static const " + _kFb + ".Reader<" + enum_type + "> reader = _" +
+ enum_type + "Reader();\n\n";
code += " @override\n";
code += " String toString() {\n";
- code += " return '" + name + "{value: $value}';\n";
+ code += " return '" + enum_type + "{value: $value}';\n";
code += " }\n";
code += "}\n\n";
- GenEnumReader(enum_def, name, &code);
- (*namespace_code)[ns] += code;
+ GenEnumReader(enum_def, enum_type, 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";
+ void GenEnumReader(EnumDef &enum_def, const std::string &enum_type,
+ std::string &code) {
+ code += "class _" + enum_type + "Reader extends " + _kFb + ".Reader<" +
+ enum_type + "> {\n";
+ code += " const _" + enum_type + "Reader();\n\n";
code += " @override\n";
- code += " int get size => 1;\n\n";
+ code += " int get size => " + EnumSize(enum_def.underlying_type) + ";\n\n";
code += " @override\n";
- code +=
- " " + name + " read(" + _kFb + ".BufferContext bc, int offset) =>\n";
- code += " new " + name + ".fromValue(const " + _kFb + "." +
+ code += " " + enum_type + " read(" + _kFb +
+ ".BufferContext bc, int offset) =>\n";
+ code += " " + enum_type + ".fromValue(const " + _kFb + "." +
GenType(enum_def.underlying_type) + "Reader().read(bc, offset));\n";
code += "}\n\n";
}
- static std::string GenType(const Type &type) {
+ std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_BOOL: return "Bool";
case BASE_TYPE_CHAR: return "Int8";
@@ -319,45 +319,74 @@ class DartGenerator : public BaseGenerator {
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";
+ case BASE_TYPE_STRUCT: return namer_.Type(*type.struct_def);
+ case BASE_TYPE_UNION: return namer_.Type(*type.enum_def) + "TypeId";
default: return "Table";
}
}
+ static std::string EnumSize(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL:
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_UCHAR: return "1";
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: return "2";
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_FLOAT: return "4";
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG:
+ case BASE_TYPE_DOUBLE: return "8";
+ default: return "1";
+ }
+ }
+
std::string GenReaderTypeName(const Type &type, Namespace *current_namespace,
const FieldDef &def,
- bool parent_is_vector = false) {
+ bool parent_is_vector = false, bool lazy = true,
+ bool constConstruct = true) {
+ std::string prefix = (constConstruct ? "const " : "") + _kFb;
if (type.base_type == BASE_TYPE_BOOL) {
- return "const " + _kFb + ".BoolReader()";
+ return prefix + ".BoolReader()";
} else if (IsVector(type)) {
- return "const " + _kFb + ".ListReader<" +
+ if (!type.VectorType().enum_def) {
+ if (type.VectorType().base_type == BASE_TYPE_CHAR) {
+ return prefix + ".Int8ListReader(" + (lazy ? ")" : "lazy: false)");
+ }
+ if (type.VectorType().base_type == BASE_TYPE_UCHAR) {
+ return prefix + ".Uint8ListReader(" + (lazy ? ")" : "lazy: false)");
+ }
+ }
+ return prefix + ".ListReader<" +
GenDartTypeName(type.VectorType(), current_namespace, def) + ">(" +
- GenReaderTypeName(type.VectorType(), current_namespace, def,
- true) +
- ")";
+ GenReaderTypeName(type.VectorType(), current_namespace, def, true,
+ true, false) +
+ (lazy ? ")" : ", lazy: false)");
} else if (IsString(type)) {
- return "const " + _kFb + ".StringReader()";
+ return prefix + ".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()";
+ return prefix + "." + 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) {
+ const FieldDef &def,
+ std::string struct_type_suffix = "") {
if (type.enum_def) {
if (type.enum_def->is_union && type.base_type != BASE_TYPE_UNION) {
- return type.enum_def->name + "TypeId";
+ return namer_.Type(*type.enum_def) + "TypeId";
} else if (type.enum_def->is_union) {
return "dynamic";
} else if (type.base_type != BASE_TYPE_VECTOR) {
- return type.enum_def->name;
+ return namer_.Type(*type.enum_def);
}
}
@@ -376,32 +405,39 @@ class DartGenerator : public BaseGenerator {
case BASE_TYPE_STRING: return "String";
case BASE_TYPE_STRUCT:
return MaybeWrapNamespace(
- type.struct_def->name + (addBuilder ? "ObjectBuilder" : ""),
+ namer_.Type(*type.struct_def) + struct_type_suffix,
current_namespace, def);
case BASE_TYPE_VECTOR:
return "List<" +
GenDartTypeName(type.VectorType(), current_namespace, def,
- addBuilder) +
+ struct_type_suffix) +
">";
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);
- }
+ std::string GenDartTypeName(const Type &type, Namespace *current_namespace,
+ const FieldDef &def, bool nullable,
+ std::string struct_type_suffix) {
+ std::string typeName =
+ GenDartTypeName(type, current_namespace, def, struct_type_suffix);
+ if (nullable && typeName != "dynamic") typeName += "?";
+ return typeName;
+ }
- if (field_ns_str != "" && field_ns_str != curr_ns_str) {
- return ImportAliasName(field_ns_str) + "." + type_name;
+ std::string MaybeWrapNamespace(const std::string &type_name,
+ Namespace *current_ns,
+ const FieldDef &field) const {
+ const std::string current_namespace = namer_.Namespace(*current_ns);
+ const std::string field_namespace =
+ field.value.type.struct_def
+ ? namer_.Namespace(*field.value.type.struct_def->defined_namespace)
+ : field.value.type.enum_def
+ ? namer_.Namespace(*field.value.type.enum_def->defined_namespace)
+ : "";
+
+ if (field_namespace != "" && field_namespace != current_namespace) {
+ return ImportAliasName(field_namespace) + "." + type_name;
} else {
return type_name;
}
@@ -409,38 +445,38 @@ class DartGenerator : public BaseGenerator {
// Generate an accessor struct with constructor for a flatbuffers struct.
void GenStruct(const StructDef &struct_def,
- namespace_code_map *namespace_code) {
+ namespace_code_map &namespace_code) {
if (struct_def.generated) return;
- auto object_namespace = BuildNamespaceName(*struct_def.defined_namespace);
- std::string code;
+ std::string &code =
+ namespace_code[namer_.Namespace(*struct_def.defined_namespace)];
- const auto &object_name = struct_def.name;
+ const auto &struct_type = namer_.Type(struct_def);
// Emit constructor
- GenDocComment(struct_def.doc_comment, &code, "");
+ 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";
+ auto reader_name = "_" + struct_type + "Reader";
+ auto builder_name = struct_type + "Builder";
+ auto object_builder_name = struct_type + "ObjectBuilder";
std::string reader_code, builder_code;
- code += "class " + object_name + " {\n";
+ code += "class " + struct_type + " {\n";
- code += " " + object_name + "._(this._bc, this._bcOffset);\n";
+ code += " " + struct_type + "._(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 += " factory " + struct_type + "(List<int> bytes) {\n";
+ code +=
+ " final rootRef = " + _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 += " static const " + _kFb + ".Reader<" + struct_type +
+ "> reader = " + reader_name + "();\n\n";
code += " final " + _kFb + ".BufferContext _bc;\n";
code += " final int _bcOffset;\n\n";
@@ -448,25 +484,154 @@ class DartGenerator : public BaseGenerator {
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;
+ FieldDef &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);
+ GenImplementationGetters(struct_def, non_deprecated_fields, code);
+
+ if (parser_.opts.generate_object_based_api) {
+ code +=
+ "\n" + GenStructObjectAPIUnpack(struct_def, non_deprecated_fields);
+
+ code += "\n static int pack(fb.Builder fbBuilder, " +
+ namer_.ObjectType(struct_def) + "? object) {\n";
+ code += " if (object == null) return 0;\n";
+ code += " return object.pack(fbBuilder);\n";
+ code += " }\n";
+ }
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);
+ if (parser_.opts.generate_object_based_api) {
+ code += GenStructObjectAPI(struct_def, non_deprecated_fields);
+ }
+
+ 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;
+ }
+
+ // Generate an accessor struct with constructor for a flatbuffers struct.
+ std::string GenStructObjectAPI(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields) {
+ std::string code;
+ GenDocComment(struct_def.doc_comment, "", code);
+
+ std::string object_type = namer_.ObjectType(struct_def);
+ code += "class " + object_type + " implements " + _kFb + ".Packable {\n";
+
+ std::string constructor_args;
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ const FieldDef &field = *it->second;
+
+ const std::string field_name = namer_.Field(field);
+ const std::string defaultValue = getDefaultValue(field.value);
+ const std::string type_name =
+ GenDartTypeName(field.value.type, struct_def.defined_namespace, field,
+ defaultValue.empty() && !struct_def.fixed, "T");
+
+ GenDocComment(field.doc_comment, " ", code);
+ code += " " + type_name + " " + field_name + ";\n";
+
+ if (!constructor_args.empty()) constructor_args += ",\n";
+ constructor_args += " ";
+ constructor_args += (struct_def.fixed ? "required " : "");
+ constructor_args += "this." + field_name;
+ if (!struct_def.fixed && !defaultValue.empty()) {
+ if (IsEnum(field.value.type)) {
+ auto &enum_def = *field.value.type.enum_def;
+ if (auto val = enum_def.FindByValue(defaultValue)) {
+ constructor_args += " = " + namer_.EnumVariant(enum_def, *val);
+ } else {
+ constructor_args += " = const " + namer_.Type(enum_def) + "._(" +
+ defaultValue + ")";
+ }
+ } else {
+ constructor_args += " = " + defaultValue;
+ }
+ }
+ }
+
+ if (!constructor_args.empty()) {
+ code += "\n " + object_type + "({\n" + constructor_args + "});\n\n";
+ }
+
+ code += GenStructObjectAPIPack(struct_def, non_deprecated_fields);
+ code += "\n";
+ code += GenToString(object_type, non_deprecated_fields);
+
+ code += "}\n\n";
+ return code;
+ }
+
+ // Generate function `StructNameT unpack()`
+ std::string GenStructObjectAPIUnpack(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields) {
+ std::string constructor_args;
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ const FieldDef &field = *it->second;
+
+ const std::string field_name = namer_.Field(field);
+ if (!constructor_args.empty()) constructor_args += ",\n";
+ constructor_args += " " + field_name + ": ";
+
+ const Type &type = field.value.type;
+ std::string defaultValue = getDefaultValue(field.value);
+ bool isNullable = defaultValue.empty() && !struct_def.fixed;
+ std::string nullableValueAccessOperator = isNullable ? "?" : "";
+ if (type.base_type == BASE_TYPE_STRUCT) {
+ constructor_args +=
+ field_name + nullableValueAccessOperator + ".unpack()";
+ } else if (type.base_type == BASE_TYPE_VECTOR) {
+ if (type.VectorType().base_type == BASE_TYPE_STRUCT) {
+ constructor_args += field_name + nullableValueAccessOperator +
+ ".map((e) => e.unpack()).toList()";
+ } else {
+ constructor_args +=
+ GenReaderTypeName(field.value.type, struct_def.defined_namespace,
+ field, false, false);
+ constructor_args += ".vTableGet";
+ std::string offset = NumToString(field.value.offset);
+ constructor_args +=
+ isNullable
+ ? "Nullable(_bc, _bcOffset, " + offset + ")"
+ : "(_bc, _bcOffset, " + offset + ", " + defaultValue + ")";
+ }
+ } else {
+ constructor_args += field_name;
+ }
+ }
- (*namespace_code)[object_namespace] += code;
+ const std::string object_type = namer_.ObjectType(struct_def);
+ std::string code = " " + object_type + " unpack() => " + object_type + "(";
+ if (!constructor_args.empty()) code += "\n" + constructor_args;
+ code += ");\n";
+ return code;
+ }
+
+ // Generate function `StructNameT pack()`
+ std::string GenStructObjectAPIPack(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields) {
+ std::string code;
+
+ code += " @override\n";
+ code += " int pack(fb.Builder fbBuilder) {\n";
+ code += GenObjectBuilderImplementation(struct_def, non_deprecated_fields,
+ false, true);
+ code += " }\n";
+ return code;
}
std::string NamespaceAliasFromUnionType(Namespace *root_namespace,
@@ -476,7 +641,7 @@ class DartGenerator : public BaseGenerator {
if (std::equal(root_namespace->components.begin(),
root_namespace->components.end(),
qualified_name_parts.begin())) {
- return type.struct_def->name;
+ return namer_.Type(*type.struct_def);
}
std::string ns;
@@ -496,40 +661,39 @@ class DartGenerator : public BaseGenerator {
if (it != qualified_name_parts.end() - 1) { ns += "_"; }
}
- return ns + "." + type.struct_def->name;
+ return ns + "." + namer_.Type(*type.struct_def);
}
void GenImplementationGetters(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
- std::string field_name = MakeCamel(field.name, false);
- std::string type_name = GenDartTypeName(
- field.value.type, struct_def.defined_namespace, field, false);
+ const std::string field_name = namer_.Field(field);
+ const std::string defaultValue = getDefaultValue(field.value);
+ const bool isNullable = defaultValue.empty() && !struct_def.fixed;
+ const std::string type_name =
+ GenDartTypeName(field.value.type, struct_def.defined_namespace, field,
+ isNullable, "");
- GenDocComment(field.doc_comment, &code, "", " ");
+ 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;
+ const 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(
+ const auto &ev = **en_it;
+ const 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";
+ enum_name + ".reader.vTableGetNullable(_bc, _bcOffset, " +
+ NumToString(field.value.offset) + ");\n";
}
code += " default: return null;\n";
code += " }\n";
@@ -538,10 +702,9 @@ class DartGenerator : public BaseGenerator {
code += " => ";
if (field.value.type.enum_def &&
field.value.type.base_type != BASE_TYPE_VECTOR) {
- code += "new " +
- GenDartTypeName(field.value.type,
+ code += GenDartTypeName(field.value.type,
struct_def.defined_namespace, field) +
- ".fromValue(";
+ (isNullable ? "._createOrNull(" : ".fromValue(");
}
code += GenReaderTypeName(field.value.type,
@@ -550,33 +713,13 @@ class DartGenerator : public BaseGenerator {
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;
- }
+ code += ".vTableGet";
+ std::string offset = NumToString(field.value.offset);
+ if (isNullable) {
+ code += "Nullable(_bc, _bcOffset, " + offset + ")";
} else {
- if (IsBool(field.value.type.base_type)) {
- code += "false";
- } else if (IsScalar(field.value.type.base_type)) {
- code += "0";
- } else {
- code += "null";
- }
+ code += "(_bc, _bcOffset, " + offset + ", " + defaultValue + ")";
}
- code += ")";
}
if (field.value.type.enum_def &&
field.value.type.base_type != BASE_TYPE_VECTOR) {
@@ -587,27 +730,61 @@ class DartGenerator : public BaseGenerator {
}
code += "\n";
+ code += GenToString(namer_.Type(struct_def), non_deprecated_fields);
+ }
+ std::string GenToString(
+ const std::string &object_name,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields) {
+ std::string code;
code += " @override\n";
code += " String toString() {\n";
- code += " return '" + struct_def.name + "{";
+ code += " return '" + object_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);
+ const std::string field = namer_.Field(*it->second);
+ // We need to escape the fact that some fields have $ in the name which is
+ // also used in symbol/string substitution.
+ std::string escaped_field;
+ for (size_t i = 0; i < field.size(); i++) {
+ if (field[i] == '$') escaped_field.push_back('\\');
+ escaped_field.push_back(field[i]);
+ }
+ code += escaped_field + ": ${" + field + "}";
if (it != non_deprecated_fields.end() - 1) { code += ", "; }
}
code += "}';\n";
code += " }\n";
+ return code;
}
- 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;
+ std::string getDefaultValue(const Value &value) const {
+ if (!value.constant.empty() && value.constant != "0") {
+ if (IsBool(value.type.base_type)) {
+ return "true";
+ }
+ if (IsScalar(value.type.base_type)) {
+ if (StringIsFlatbufferNan(value.constant)) {
+ return "double.nan";
+ } else if (StringIsFlatbufferPositiveInfinity(value.constant)) {
+ return "double.infinity";
+ } else if (StringIsFlatbufferNegativeInfinity(value.constant)) {
+ return "double.negativeInfinity";
+ }
+ }
+ return value.constant;
+ } else if (IsBool(value.type.base_type)) {
+ return "false";
+ } else if (IsScalar(value.type.base_type) && !IsUnion(value.type)) {
+ return "0";
+ } else {
+ return "";
+ }
+ }
+
+ void GenReader(const StructDef &struct_def, const std::string &reader_name,
+ std::string &code) {
+ const auto struct_type = namer_.Type(struct_def);
code += "class " + reader_name + " extends " + _kFb;
if (struct_def.fixed) {
@@ -615,7 +792,7 @@ class DartGenerator : public BaseGenerator {
} else {
code += ".TableReader<";
}
- code += impl_name + "> {\n";
+ code += struct_type + "> {\n";
code += " const " + reader_name + "();\n\n";
if (struct_def.fixed) {
@@ -623,29 +800,26 @@ class DartGenerator : public BaseGenerator {
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 += " " + struct_type +
+ " createObject(fb.BufferContext bc, int offset) => \n " +
+ struct_type + "._(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) {
+ void GenBuilder(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ const std::string &builder_name, std::string &code) {
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 += " " + builder_name + "(this.fbBuilder);\n\n";
code += " final " + _kFb + ".Builder fbBuilder;\n\n";
if (struct_def.fixed) {
- StructBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ StructBuilderBody(struct_def, non_deprecated_fields, code);
} else {
- TableBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ TableBuilderBody(struct_def, non_deprecated_fields, code);
}
code += "}\n\n";
@@ -653,15 +827,13 @@ class DartGenerator : public BaseGenerator {
void StructBuilderBody(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
code += " int finish(";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (IsStruct(field.value.type)) {
code += "fb.StructBuilder";
@@ -669,26 +841,26 @@ class DartGenerator : public BaseGenerator {
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
}
- code += " " + field.name;
+ 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;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
}
if (IsStruct(field.value.type)) {
- code += " " + field.name + "();\n";
+ code += " " + field_name + "();\n";
} else {
code += " fbBuilder.put" + GenType(field.value.type) + "(";
- code += field.name;
- if (field.value.type.enum_def) { code += "?.value"; }
+ code += field_name;
+ if (field.value.type.enum_def) { code += ".value"; }
code += ");\n";
}
}
@@ -698,36 +870,36 @@ class DartGenerator : public BaseGenerator {
void TableBuilderBody(
const StructDef &struct_def,
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr) {
- auto &code = *code_ptr;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ std::string &code) {
code += " void begin() {\n";
- code += " fbBuilder.startTable();\n";
+ code += " fbBuilder.startTable(" +
+ NumToString(struct_def.fields.vec.size()) + ");\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;
+ const auto &field = *it->second;
+ const auto offset = it->first;
+ const std::string add_field = namer_.Method("add", field);
+ const std::string field_var = namer_.Variable(field);
if (IsScalar(field.value.type.base_type)) {
- code += " int add" + MakeCamel(field.name) + "(";
+ code += " int " + add_field + "(";
code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
field);
- code += " " + MakeCamel(field.name, false) + ") {\n";
+ code += "? " + field_var + ") {\n";
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
NumToString(offset) + ", ";
- code += MakeCamel(field.name, false);
+ code += field_var;
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 += " int " + add_field + "(int offset) {\n";
code +=
" fbBuilder.addStruct(" + NumToString(offset) + ", offset);\n";
} else {
- code += " int add" + MakeCamel(field.name) + "Offset(int offset) {\n";
+ code += " int " + add_field + "Offset(int? offset) {\n";
code +=
" fbBuilder.addOffset(" + NumToString(offset) + ", offset);\n";
}
@@ -743,21 +915,17 @@ class DartGenerator : public BaseGenerator {
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;
-
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ const std::string &builder_name, std::string &code) {
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;
+ const FieldDef &field = *it->second;
code += " final " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
- field, true) +
- " _" + MakeCamel(field.name, false) + ";\n";
+ field, !struct_def.fixed, "ObjectBuilder") +
+ " _" + namer_.Variable(field) + ";\n";
}
code += "\n";
code += " " + builder_name + "(";
@@ -766,23 +934,21 @@ class DartGenerator : public BaseGenerator {
code += "{\n";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
- code += " " +
+ code += " ";
+ code += (struct_def.fixed ? "required " : "") +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
- field, true) +
- " " + MakeCamel(field.name, false) + ",\n";
+ field, !struct_def.fixed, "ObjectBuilder") +
+ " " + namer_.Variable(field) + ",\n";
}
code += " })\n";
code += " : ";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
- code += "_" + MakeCamel(field.name, false) + " = " +
- MakeCamel(field.name, false);
+ code += "_" + namer_.Variable(field) + " = " + namer_.Variable(field);
if (it == non_deprecated_fields.end() - 1) {
code += ";\n\n";
} else {
@@ -795,80 +961,105 @@ class DartGenerator : public BaseGenerator {
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";
+ code += " int finish(" + _kFb + ".Builder fbBuilder) {\n";
+ code += GenObjectBuilderImplementation(struct_def, non_deprecated_fields);
+ code += " }\n\n";
+
+ code += " /// Convenience method to serialize to byte list.\n";
+ code += " @override\n";
+ code += " Uint8List toBytes([String? fileIdentifier]) {\n";
+ code += " final fbBuilder = " + _kFb +
+ ".Builder(deduplicateTables: false);\n";
+ code += " fbBuilder.finish(finish(fbBuilder), fileIdentifier);\n";
+ code += " return fbBuilder.buffer;\n";
+ code += " }\n";
+ code += "}\n";
+ }
+ std::string GenObjectBuilderImplementation(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ bool prependUnderscore = true, bool pack = false) {
+ std::string code;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->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)) {
+ std::string offset_name = namer_.Variable(field) + "Offset";
+ std::string field_name =
+ (prependUnderscore ? "_" : "") + namer_.Variable(field);
+ // custom handling for fixed-sized struct in pack()
+ if (pack && IsVector(field.value.type) &&
+ field.value.type.VectorType().base_type == BASE_TYPE_STRUCT &&
+ field.value.type.struct_def->fixed) {
+ code += " int? " + offset_name + ";\n";
+ code += " if (" + field_name + " != null) {\n";
code +=
- " = _" + MakeCamel(field.name, false) + "?.isNotEmpty == true\n";
- code += " ? fbBuilder.writeList";
+ " for (var e in " + field_name + "!) { e.pack(fbBuilder); }\n";
+ code += " " + namer_.Variable(field) +
+ "Offset = fbBuilder.endStructVector(" + field_name +
+ "!.length);\n";
+ code += " }\n";
+ continue;
+ }
+
+ code += " final int? " + offset_name;
+ if (IsVector(field.value.type)) {
+ code += " = " + field_name + " == null ? null\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())";
+ code +=
+ "(" + field_name + "!.map(fbBuilder.writeString).toList());\n";
break;
case BASE_TYPE_STRUCT:
if (field.value.type.struct_def->fixed) {
- code += "OfStructs(_" + MakeCamel(field.name, false) + ")";
+ code += "OfStructs(" + field_name + "!);\n";
} else {
- code += "(_" + MakeCamel(field.name, false) +
- ".map((b) => b.getOrCreateOffset(fbBuilder)).toList())";
+ code += "(" + field_name + "!.map((b) => b." +
+ (pack ? "pack" : "getOrCreateOffset") +
+ "(fbBuilder)).toList());\n";
}
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 +=
+ GenType(field.value.type.VectorType()) + "(" + field_name + "!";
+ if (field.value.type.enum_def) {
+ code += ".map((f) => f.value).toList()";
+ }
+ code += ");\n";
}
- code += "\n : null;\n";
} else if (IsString(field.value.type)) {
- code += " = fbBuilder.writeString(_" + MakeCamel(field.name, false) +
- ");\n";
+ code += " = " + field_name + " == null ? null\n";
+ code += " : fbBuilder.writeString(" + field_name + "!);\n";
} else {
- code += " = _" + MakeCamel(field.name, false) +
- "?.getOrCreateOffset(fbBuilder);\n";
+ code += " = " + field_name + "?." +
+ (pack ? "pack" : "getOrCreateOffset") + "(fbBuilder);\n";
}
}
- code += "\n";
if (struct_def.fixed) {
- StructObjectBuilderBody(non_deprecated_fields, code_ptr);
+ code += StructObjectBuilderBody(non_deprecated_fields, prependUnderscore,
+ pack);
} else {
- TableObjectBuilderBody(non_deprecated_fields, code_ptr);
+ code += TableObjectBuilderBody(struct_def, non_deprecated_fields,
+ prependUnderscore, pack);
}
- 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";
+ return code;
}
- void StructObjectBuilderBody(
- std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
- std::string *code_ptr, bool prependUnderscore = true) {
- auto &code = *code_ptr;
+ std::string StructObjectBuilderBody(
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ bool prependUnderscore = true, bool pack = false) {
+ std::string code;
for (auto it = non_deprecated_fields.rbegin();
it != non_deprecated_fields.rend(); ++it) {
- auto pair = *it;
- auto &field = *pair.second;
+ const FieldDef &field = *it->second;
+ const std::string field_name = namer_.Field(field);
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
@@ -877,55 +1068,59 @@ class DartGenerator : public BaseGenerator {
if (IsStruct(field.value.type)) {
code += " ";
if (prependUnderscore) { code += "_"; }
- code += field.name + ".finish(fbBuilder);\n";
+ code += field_name + (pack ? ".pack" : ".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 += field_name;
+ if (field.value.type.enum_def) { code += ".value"; }
code += ");\n";
}
}
code += " return fbBuilder.offset;\n";
+ return code;
}
- 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";
+ std::string TableObjectBuilderBody(
+ const StructDef &struct_def,
+ const std::vector<std::pair<int, FieldDef *>> &non_deprecated_fields,
+ bool prependUnderscore = true, bool pack = false) {
+ std::string code;
+ code += " fbBuilder.startTable(" +
+ NumToString(struct_def.fields.vec.size()) + ");\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;
+ const FieldDef &field = *it->second;
+ auto offset = it->first;
+
+ std::string field_var =
+ (prependUnderscore ? "_" : "") + namer_.Variable(field);
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"; }
+ NumToString(offset) + ", " + field_var;
+ if (field.value.type.enum_def) {
+ bool isNullable = getDefaultValue(field.value).empty();
+ code += (isNullable || !pack) ? "?.value" : ".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 += " if (" + field_var + " != null) {\n";
+ code += " fbBuilder.addStruct(" + NumToString(offset) + ", " +
+ field_var + (pack ? "!.pack" : "!.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 += " fbBuilder.addOffset(" + NumToString(offset) + ", " +
+ namer_.Variable(field) + "Offset);\n";
}
}
code += " return fbBuilder.endTable();\n";
+ return code;
}
+
+ const IdlNamer namer_;
};
} // namespace dart
@@ -937,13 +1132,10 @@ bool GenerateDart(const Parser &parser, const std::string &path,
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 make_rule = generator.Filename("") + ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
@@ -952,4 +1144,58 @@ std::string DartMakeRule(const Parser &parser, const std::string &path,
return make_rule;
}
+namespace {
+
+class DartCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateDart(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = DartMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kDart; }
+
+ std::string LanguageName() const override { return "Dart"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewDartCodeGenerator() {
+ return std::unique_ptr<DartCodeGenerator>(new DartCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_dart.h b/contrib/libs/flatbuffers/src/idl_gen_dart.h
new file mode 100644
index 0000000000..efaa08e39b
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_dart.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_DART_H_
+#define FLATBUFFERS_IDL_GEN_DART_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Dart code generator.
+std::unique_ptr<CodeGenerator> NewDartCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_DART_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp b/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
index 35c1a7d4f5..f71c21f97d 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
@@ -15,7 +15,13 @@
*/
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_fbs.h"
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "flatbuffers/code_generator.h"
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
@@ -34,9 +40,201 @@ static std::string GenType(const Type &type, bool underlying = false) {
return type.enum_def->defined_namespace->GetFullyQualifiedName(
type.enum_def->name);
} else {
- return kTypeNames[type.base_type];
+ return TypeName(type.base_type);
+ }
+ }
+}
+
+static bool HasFieldWithId(const std::vector<FieldDef *> &fields) {
+ static const std::string ID = "id";
+
+ for (const auto *field : fields) {
+ const auto *id_attribute = field->attributes.Lookup(ID);
+ if (id_attribute != nullptr && !id_attribute->constant.empty()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool HasNonPositiveFieldId(const std::vector<FieldDef *> &fields) {
+ static const std::string ID = "id";
+
+ for (const auto *field : fields) {
+ const auto *id_attribute = field->attributes.Lookup(ID);
+ if (id_attribute != nullptr && !id_attribute->constant.empty()) {
+ voffset_t proto_id = 0;
+ bool done = StringToNumber(id_attribute->constant.c_str(), &proto_id);
+ if (!done) { return true; }
+ }
+ }
+ return false;
+}
+
+static bool HasFieldIdFromReservedIds(
+ const std::vector<FieldDef *> &fields,
+ const std::vector<voffset_t> &reserved_ids) {
+ static const std::string ID = "id";
+
+ for (const auto *field : fields) {
+ const auto *id_attribute = field->attributes.Lookup(ID);
+ if (id_attribute != nullptr && !id_attribute->constant.empty()) {
+ voffset_t proto_id = 0;
+ bool done = StringToNumber(id_attribute->constant.c_str(), &proto_id);
+ if (!done) { return true; }
+ auto id_it =
+ std::find(std::begin(reserved_ids), std::end(reserved_ids), proto_id);
+ if (id_it != reserved_ids.end()) { return true; }
+ }
+ }
+ return false;
+}
+
+static std::vector<voffset_t> ExtractProtobufIds(
+ const std::vector<FieldDef *> &fields) {
+ static const std::string ID = "id";
+ std::vector<voffset_t> used_proto_ids;
+ for (const auto *field : fields) {
+ const auto *id_attribute = field->attributes.Lookup(ID);
+ if (id_attribute != nullptr && !id_attribute->constant.empty()) {
+ voffset_t proto_id = 0;
+ bool done = StringToNumber(id_attribute->constant.c_str(), &proto_id);
+ if (done) { used_proto_ids.push_back(proto_id); }
+ }
+ }
+
+ return used_proto_ids;
+}
+
+static bool HasTwiceUsedId(const std::vector<FieldDef *> &fields) {
+ std::vector<voffset_t> used_proto_ids = ExtractProtobufIds(fields);
+ std::sort(std::begin(used_proto_ids), std::end(used_proto_ids));
+ for (auto it = std::next(std::begin(used_proto_ids));
+ it != std::end(used_proto_ids); it++) {
+ if (*it == *std::prev(it)) { return true; }
+ }
+
+ return false;
+}
+
+static bool HasGapInProtoId(const std::vector<FieldDef *> &fields) {
+ std::vector<voffset_t> used_proto_ids = ExtractProtobufIds(fields);
+ std::sort(std::begin(used_proto_ids), std::end(used_proto_ids));
+ for (auto it = std::next(std::begin(used_proto_ids));
+ it != std::end(used_proto_ids); it++) {
+ if (*it != *std::prev(it) + 1) { return true; }
+ }
+
+ return false;
+}
+
+static bool ProtobufIdSanityCheck(const StructDef &struct_def,
+ IDLOptions::ProtoIdGapAction gap_action,
+ bool no_log = false) {
+ const auto &fields = struct_def.fields.vec;
+ if (HasNonPositiveFieldId(fields)) {
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr, "Field id in struct %s has a non positive number value\n",
+ struct_def.name.c_str());
+ }
+ return false;
+ }
+
+ if (HasTwiceUsedId(fields)) {
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr, "Fields in struct %s have used an id twice\n",
+ struct_def.name.c_str());
+ }
+ return false;
+ }
+
+ if (HasFieldIdFromReservedIds(fields, struct_def.reserved_ids)) {
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr, "Fields in struct %s use id from reserved ids\n",
+ struct_def.name.c_str());
+ }
+ return false;
+ }
+
+ if (gap_action != IDLOptions::ProtoIdGapAction::NO_OP) {
+ if (HasGapInProtoId(fields)) {
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr, "Fields in struct %s have gap between ids\n",
+ struct_def.name.c_str());
}
+ if (gap_action == IDLOptions::ProtoIdGapAction::ERROR) { return false; }
+ }
}
+
+ return true;
+}
+
+struct ProtobufToFbsIdMap {
+ using FieldName = std::string;
+ using FieldID = voffset_t;
+ using FieldNameToIdMap = std::unordered_map<FieldName, FieldID>;
+
+ FieldNameToIdMap field_to_id;
+ bool successful = false;
+};
+
+static ProtobufToFbsIdMap MapProtoIdsToFieldsId(
+ const StructDef &struct_def, IDLOptions::ProtoIdGapAction gap_action,
+ bool no_log) {
+ const auto &fields = struct_def.fields.vec;
+
+ if (!HasFieldWithId(fields)) {
+ ProtobufToFbsIdMap result;
+ result.successful = true;
+ return result;
+ }
+
+ if (!ProtobufIdSanityCheck(struct_def, gap_action, no_log)) { return {}; }
+
+ static constexpr int UNION_ID = -1;
+ using ProtoIdFieldNamePair = std::pair<int, std::string>;
+ std::vector<ProtoIdFieldNamePair> proto_ids;
+
+ for (const auto *field : fields) {
+ const auto *id_attribute = field->attributes.Lookup("id");
+ if (id_attribute != nullptr) {
+ // When we have union but do not use union flag to keep them
+ if (id_attribute->constant.empty() &&
+ field->value.type.base_type == BASE_TYPE_UNION) {
+ proto_ids.emplace_back(UNION_ID, field->name);
+ } else {
+ voffset_t proto_id = 0;
+ StringToNumber(id_attribute->constant.c_str(), &proto_id);
+ proto_ids.emplace_back(proto_id, field->name);
+ }
+ } else {
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr, "Fields id in struct %s is missing\n",
+ struct_def.name.c_str());
+ }
+ return {};
+ }
+ }
+
+ std::sort(
+ std::begin(proto_ids), std::end(proto_ids),
+ [](const ProtoIdFieldNamePair &rhs, const ProtoIdFieldNamePair &lhs) {
+ return rhs.first < lhs.first;
+ });
+ struct ProtobufToFbsIdMap proto_to_fbs;
+
+ voffset_t id = 0;
+ for (const auto &element : proto_ids) {
+ if (element.first == UNION_ID) { id++; }
+ proto_to_fbs.field_to_id.emplace(element.second, id++);
+ }
+ proto_to_fbs.successful = true;
+ return proto_to_fbs;
}
static void GenNameSpace(const Namespace &name_space, std::string *_schema,
@@ -54,7 +252,8 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
}
// Generate a flatbuffer schema from the Parser's internal representation.
-std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
+std::string GenerateFBS(const Parser &parser, const std::string &file_name,
+ bool no_log = false) {
// 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();
@@ -79,10 +278,11 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
int num_includes = 0;
for (auto it = parser.included_files_.begin();
it != parser.included_files_.end(); ++it) {
- if (it->second.empty())
+ if (it->second.empty()) {
continue;
+}
std::string basename;
- if(parser.opts.keep_include_path) {
+ if(parser.opts.keep_prefix) {
basename = flatbuffers::StripExtension(it->second);
} else {
basename = flatbuffers::StripPath(
@@ -94,6 +294,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
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();
@@ -104,18 +305,22 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
}
GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
GenComment(enum_def.doc_comment, &schema, nullptr);
- if (enum_def.is_union)
+ if (enum_def.is_union) {
schema += "union " + enum_def.name;
- else
+ } 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)
+ if (enum_def.is_union) {
schema += " " + GenType(ev.union_type) + ",\n";
- else
+ } else {
schema += " " + ev.name + " = " + enum_def.ToString(ev) + ",\n";
+ }
}
schema += "}\n\n";
}
@@ -123,9 +328,14 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
++it) {
StructDef &struct_def = **it;
+ const auto proto_fbs_ids = MapProtoIdsToFieldsId(
+ struct_def, parser.opts.proto_id_gap_action, no_log);
+ if (!proto_fbs_ids.successful) { return {}; }
+
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";
@@ -136,7 +346,26 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
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)";
+ std::vector<std::string> attributes;
+ if (field.IsRequired()) attributes.push_back("required");
+ if (field.key) attributes.push_back("key");
+
+ if (parser.opts.keep_proto_id) {
+ auto it = proto_fbs_ids.field_to_id.find(field.name);
+ if (it != proto_fbs_ids.field_to_id.end()) {
+ attributes.push_back("id: " + NumToString(it->second));
+ } // If not found it means we do not have any ids
+ }
+
+ if (!attributes.empty()) {
+ schema += " (";
+ for (const auto &attribute : attributes) {
+ schema += attribute + ",";
+ }
+ schema.pop_back();
+ schema += ")";
+ }
+
schema += ";\n";
}
}
@@ -146,9 +375,81 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
}
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);
+ const std::string &file_name, bool no_log = false) {
+ const std::string fbs = GenerateFBS(parser, file_name, no_log);
+ if (fbs.empty()) { return false; }
+ // TODO: Use LogCompilerWarn
+ if (!no_log) {
+ fprintf(stderr,
+ "When you use --proto, that you should check for conformity "
+ "yourself, using the existing --conform");
+ }
+ return SaveFile((path + file_name + ".fbs").c_str(), fbs, false);
+}
+
+namespace {
+
+class FBSCodeGenerator : public CodeGenerator {
+ public:
+ explicit FBSCodeGenerator(const bool no_log) : no_log_(no_log) {}
+
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateFBS(parser, path, filename, no_log_)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ // Generate code from the provided `buffer` of given `length`. The buffer is a
+ // serialized reflection.fbs.
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return false; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kProto; }
+
+ std::string LanguageName() const override { return "proto"; }
+
+ protected:
+ const bool no_log_;
+};
+
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewFBSCodeGenerator(const bool no_log) {
+ return std::unique_ptr<FBSCodeGenerator>(new FBSCodeGenerator(no_log));
}
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_fbs.h b/contrib/libs/flatbuffers/src/idl_gen_fbs.h
new file mode 100644
index 0000000000..403f160b9b
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_fbs.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 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_GEN_FBS_H_
+#define FLATBUFFERS_IDL_GEN_FBS_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+std::unique_ptr<CodeGenerator> NewFBSCodeGenerator(bool no_log = false);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_FBS_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_go.cpp b/contrib/libs/flatbuffers/src/idl_gen_go.cpp
index 867f402322..0f2882b758 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_go.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_go.cpp
@@ -16,13 +16,19 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_go.h"
+
+#include <algorithm>
+#include <cmath>
#include <sstream>
#include <string>
+#include "flatbuffers/base.h"
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
#ifdef _WIN32
# include <direct.h>
@@ -37,30 +43,56 @@ 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",
-};
+namespace {
-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); }
- }
+// see https://golang.org/ref/spec#Keywords
+static std::set<std::string> GoKeywords() {
+ return {
+ "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",
+ };
+}
- return MakeCamel(name, false);
+static Namer::Config GoDefaultConfig() {
+ // Note that the functions with user defined types in the name use
+ // upper camel case for all but the user defined type itself, which is keep
+ // cased. Despite being a function, we interpret it as a Type.
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kUpperCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kUpperCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"", // I.e. Concatenate.
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"__",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".go" };
}
+} // namespace
+
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) {
+ cur_name_space_(nullptr),
+ namer_(WithFlagOptions(GoDefaultConfig(), parser.opts, path),
+ GoKeywords()) {
std::istringstream iss(go_namespace);
std::string component;
while (std::getline(iss, component, '.')) {
@@ -73,8 +105,10 @@ class GoGenerator : public BaseGenerator {
bool needs_imports = false;
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
- tracked_imported_namespaces_.clear();
- needs_imports = false;
+ if (!parser_.opts.one_file) {
+ needs_imports = false;
+ ResetImports();
+ }
std::string enumcode;
GenEnum(**it, &enumcode);
if ((*it)->is_union && parser_.opts.generate_object_based_api) {
@@ -92,7 +126,7 @@ class GoGenerator : public BaseGenerator {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
- tracked_imported_namespaces_.clear();
+ if (!parser_.opts.one_file) { ResetImports(); }
std::string declcode;
GenStruct(**it, &declcode);
if (parser_.opts.one_file) {
@@ -118,13 +152,16 @@ class GoGenerator : public BaseGenerator {
private:
Namespace go_namespace_;
Namespace *cur_name_space_;
+ const IdlNamer namer_;
struct NamespacePtrLess {
- bool operator()(const Namespace *a, const Namespace *b) const {
- return *a < *b;
+ bool operator()(const Definition *a, const Definition *b) const {
+ return *a->defined_namespace < *b->defined_namespace;
}
};
- std::set<const Namespace *, NamespacePtrLess> tracked_imported_namespaces_;
+ std::set<const Definition *, NamespacePtrLess> tracked_imported_namespaces_;
+ bool needs_math_import_ = false;
+ bool needs_bytes_import_ = false;
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that.
@@ -137,7 +174,7 @@ class GoGenerator : public BaseGenerator {
void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "type " + struct_def.name + " struct {\n\t";
+ code += "type " + namer_.Type(struct_def) + " struct {\n\t";
// _ is reserved in flatbuffers field names, so no chance of name conflict:
code += "_tab ";
@@ -147,8 +184,7 @@ class GoGenerator : public BaseGenerator {
// 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));
+ return WrapInNameSpaceAndTrack(&enum_def, namer_.Type(enum_def));
}
// Create a type for the enum values.
@@ -169,8 +205,7 @@ class GoGenerator : public BaseGenerator {
size_t max_name_length, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\t";
- code += enum_def.name;
- code += ev.name;
+ code += namer_.EnumVariant(enum_def, ev);
code += " ";
code += std::string(max_name_length - ev.name.length(), ' ');
code += GetEnumTypeName(enum_def);
@@ -197,8 +232,7 @@ class GoGenerator : public BaseGenerator {
size_t max_name_length, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "\t";
- code += enum_def.name;
- code += ev.name;
+ code += namer_.EnumVariant(enum_def, ev);
code += ": ";
code += std::string(max_name_length - ev.name.length(), ' ');
code += "\"";
@@ -215,8 +249,9 @@ class GoGenerator : public BaseGenerator {
// 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";
+ const std::string enum_type = namer_.Type(enum_def);
+ code += "func (v " + enum_type + ") String() string {\n";
+ code += "\tif s, ok := EnumNames" + enum_type + "[v]; ok {\n";
code += "\t\treturn s\n";
code += "\t}\n";
code += "\treturn \"" + enum_def.name;
@@ -228,7 +263,7 @@ class GoGenerator : public BaseGenerator {
void BeginEnumValues(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "var EnumValues";
- code += enum_def.name;
+ code += namer_.Type(enum_def);
code += " = map[string]" + GetEnumTypeName(enum_def) + "{\n";
}
@@ -240,8 +275,7 @@ class GoGenerator : public BaseGenerator {
code += ev.name;
code += "\": ";
code += std::string(max_name_length - ev.name.length(), ' ');
- code += enum_def.name;
- code += ev.name;
+ code += namer_.EnumVariant(enum_def, ev);
code += ",\n";
}
@@ -255,13 +289,21 @@ class GoGenerator : public BaseGenerator {
void NewRootTypeFromBuffer(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
- std::string size_prefix[] = { "", "SizePrefixed" };
+ const std::string size_prefix[] = { "", "SizePrefixed" };
+ const std::string struct_type = namer_.Type(struct_def);
+
+ bool has_file_identifier = (parser_.root_struct_def_ == &struct_def) &&
+ parser_.file_identifier_.length();
+
+ if (has_file_identifier) {
+ code += "const " + struct_type + "Identifier = \"" +
+ parser_.file_identifier_ + "\"\n\n";
+ }
for (int i = 0; i < 2; i++) {
- code += "func Get" + size_prefix[i] + "RootAs";
- code += struct_def.name;
+ code += "func Get" + size_prefix[i] + "RootAs" + struct_type;
code += "(buf []byte, offset flatbuffers.UOffsetT) ";
- code += "*" + struct_def.name + "";
+ code += "*" + struct_type + "";
code += " {\n";
if (i == 0) {
code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
@@ -270,7 +312,7 @@ class GoGenerator : public BaseGenerator {
"\tn := "
"flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])\n";
}
- code += "\tx := &" + struct_def.name + "{}\n";
+ code += "\tx := &" + struct_type + "{}\n";
if (i == 0) {
code += "\tx.Init(buf, n+offset)\n";
} else {
@@ -278,6 +320,26 @@ class GoGenerator : public BaseGenerator {
}
code += "\treturn x\n";
code += "}\n\n";
+
+ code += "func Finish" + size_prefix[i] + struct_type +
+ "Buffer(builder *flatbuffers.Builder, offset "
+ "flatbuffers.UOffsetT) {\n";
+ if (has_file_identifier) {
+ code += "\tidentifierBytes := []byte(" + struct_type + "Identifier)\n";
+ code += "\tbuilder.Finish" + size_prefix[i] +
+ "WithFileIdentifier(offset, identifierBytes)\n";
+ } else {
+ code += "\tbuilder.Finish" + size_prefix[i] + "(offset)\n";
+ }
+ code += "}\n\n";
+
+ if (has_file_identifier) {
+ code += "func " + size_prefix[i] + struct_type +
+ "BufferHasIdentifier(buf []byte) bool {\n";
+ code += "\treturn flatbuffers." + size_prefix[i] +
+ "BufferHasIdentifier(buf, " + struct_type + "Identifier)\n";
+ code += "}\n\n";
+ }
}
}
@@ -315,7 +377,7 @@ class GoGenerator : public BaseGenerator {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name) + "Length(";
+ code += " " + namer_.Function(field) + "Length(";
code += ") int " + OffsetPrefix(field);
code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
code += "\treturn 0\n}\n\n";
@@ -327,7 +389,7 @@ class GoGenerator : public BaseGenerator {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name) + "Bytes(";
+ code += " " + namer_.Function(field) + "Bytes(";
code += ") []byte " + OffsetPrefix(field);
code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
code += "\treturn nil\n}\n\n";
@@ -339,7 +401,7 @@ class GoGenerator : public BaseGenerator {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " {\n";
code += "\treturn " +
CastToEnum(field.value.type,
@@ -354,10 +416,16 @@ class GoGenerator : public BaseGenerator {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " ";
- code += OffsetPrefix(field) + "\t\treturn ";
+ code += OffsetPrefix(field);
+ if (field.IsScalarOptional()) {
+ code += "\t\tv := ";
+ } else {
+ code += "\t\treturn ";
+ }
code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)");
+ if (field.IsScalarOptional()) { code += "\n\t\treturn &v"; }
code += "\n\t}\n";
code += "\treturn " + GenConstant(field) + "\n";
code += "}\n\n";
@@ -369,7 +437,7 @@ class GoGenerator : public BaseGenerator {
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *" + TypeName(field);
code += ") *" + TypeName(field);
code += " {\n";
@@ -388,7 +456,7 @@ class GoGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *";
code += TypeName(field);
code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
@@ -410,7 +478,7 @@ class GoGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "() " + TypeName(field) + " ";
code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
@@ -422,7 +490,7 @@ class GoGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name) + "(";
+ code += " " + namer_.Function(field) + "(";
code += "obj " + GenTypePointer(field.value.type) + ") bool ";
code += OffsetPrefix(field);
code += "\t\t" + GenGetter(field.value.type);
@@ -438,7 +506,7 @@ class GoGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "(obj *" + TypeName(field);
code += ", j int) bool " + OffsetPrefix(field);
code += "\t\tx := rcv._tab.Vector(o)\n";
@@ -453,6 +521,36 @@ class GoGenerator : public BaseGenerator {
code += "}\n\n";
}
+ void GetMemberOfVectorOfStructByKey(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+ FLATBUFFERS_ASSERT(vectortype.struct_def->has_key);
+
+ auto &vector_struct_fields = vectortype.struct_def->fields.vec;
+ auto kit =
+ std::find_if(vector_struct_fields.begin(), vector_struct_fields.end(),
+ [&](FieldDef *vector_struct_field) {
+ return vector_struct_field->key;
+ });
+
+ auto &key_field = **kit;
+ FLATBUFFERS_ASSERT(key_field.key);
+
+ GenReceiver(struct_def, code_ptr);
+ code += " " + namer_.Field(field) + "ByKey";
+ code += "(obj *" + TypeName(field);
+ code += ", key " + NativeType(key_field.value.type) + ") bool " +
+ OffsetPrefix(field);
+ code += "\t\tx := rcv._tab.Vector(o)\n";
+ code += "\t\treturn ";
+ code += "obj.LookupByKey(key, x, rcv._tab.Bytes)\n";
+ code += "\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,
@@ -461,7 +559,7 @@ class GoGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += " " + MakeCamel(field.name);
+ code += " " + namer_.Function(field);
code += "(j int) " + TypeName(field) + " ";
code += OffsetPrefix(field);
code += "\t\ta := rcv._tab.Vector(o)\n";
@@ -509,7 +607,7 @@ class GoGenerator : public BaseGenerator {
} else {
std::string &code = *code_ptr;
code += std::string(", ") + nameprefix;
- code += GoIdentity(field.name);
+ code += namer_.Variable(field);
code += " " + TypeName(field);
}
}
@@ -539,7 +637,7 @@ class GoGenerator : public BaseGenerator {
} else {
code += "\tbuilder.Prepend" + GenMethod(field) + "(";
code += CastToBaseType(field.value.type,
- nameprefix + GoIdentity(field.name)) +
+ nameprefix + namer_.Variable(field)) +
")\n";
}
}
@@ -554,7 +652,7 @@ class GoGenerator : public BaseGenerator {
// 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 += "func " + namer_.Type(struct_def) + "Start";
code += "(builder *flatbuffers.Builder) {\n";
code += "\tbuilder.StartObject(";
code += NumToString(struct_def.fields.vec.size());
@@ -565,35 +663,45 @@ class GoGenerator : public BaseGenerator {
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);
+ const std::string field_var = namer_.Variable(field);
+ code += "func " + namer_.Type(struct_def) + "Add" + namer_.Function(field);
code += "(builder *flatbuffers.Builder, ";
- code += GoIdentity(field.name) + " ";
+ code += field_var + " ";
if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
code += "flatbuffers.UOffsetT";
} else {
- code += TypeName(field);
+ code += GenTypeGet(field.value.type);
+ }
+ code += ") {\n\t";
+ code += "builder.Prepend";
+ code += GenMethod(field);
+ if (field.IsScalarOptional()) {
+ code += "(";
+ } else {
+ code += "Slot(" + NumToString(offset) + ", ";
}
- 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) + ")";
+ code += "(" + field_var + ")";
} else {
- code += CastToBaseType(field.value.type, GoIdentity(field.name));
+ code += CastToBaseType(field.value.type, field_var);
}
- code += ", " + GenConstant(field);
- code += ")\n}\n";
+ if (field.IsScalarOptional()) {
+ code += ")\n";
+ code += "\tbuilder.Slot(" + NumToString(offset);
+ } else {
+ code += ", " + GenConstant(field);
+ }
+ code += ")\n";
+ code += "}\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 += "func " + namer_.Type(struct_def) + "Start";
+ code += namer_.Function(field);
code += "Vector(builder *flatbuffers.Builder, numElems int) ";
code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
auto vector_type = field.value.type.VectorType();
@@ -607,7 +715,7 @@ class GoGenerator : public BaseGenerator {
// 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 += "func " + namer_.Type(struct_def) + "End";
code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
code += "{\n\treturn builder.EndObject()\n}\n";
}
@@ -615,7 +723,7 @@ class GoGenerator : public BaseGenerator {
// 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 + ")";
+ code += "func (rcv *" + namer_.Type(struct_def) + ")";
}
// Generate a struct field getter, conditioned on its child type(s).
@@ -644,6 +752,12 @@ class GoGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ // TODO(michaeltle): Support querying fixed struct by key.
+ // Currently, we only support keyed tables.
+ if (!vectortype.struct_def->fixed &&
+ vectortype.struct_def->has_key) {
+ GetMemberOfVectorOfStructByKey(struct_def, field, code_ptr);
+ }
} else {
GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
}
@@ -665,11 +779,12 @@ class GoGenerator : public BaseGenerator {
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;
+ std::string setter =
+ "rcv._tab.Mutate" + namer_.Method(GenTypeBasic(field.value.type));
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + MakeCamel(field.name);
- code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
+ code += " Mutate" + namer_.Function(field);
+ code +=
+ "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn " + setter;
code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
code += NumToString(field.value.offset) + "), ";
code += CastToBaseType(field.value.type, "n") + ")\n}\n\n";
@@ -679,11 +794,11 @@ class GoGenerator : public BaseGenerator {
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";
+ std::string setter = "rcv._tab.Mutate" +
+ namer_.Method(GenTypeBasic(field.value.type)) + "Slot";
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + MakeCamel(field.name);
- code += "(n " + TypeName(field) + ") bool {\n\treturn ";
+ code += " Mutate" + namer_.Function(field);
+ code += "(n " + GenTypeGet(field.value.type) + ") bool {\n\treturn ";
code += setter + "(" + NumToString(field.value.offset) + ", ";
code += CastToBaseType(field.value.type, "n") + ")\n";
code += "}\n\n";
@@ -695,10 +810,10 @@ class GoGenerator : public BaseGenerator {
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;
+ std::string setter =
+ "rcv._tab.Mutate" + namer_.Method(GenTypeBasic(vectortype));
GenReceiver(struct_def, code_ptr);
- code += " Mutate" + MakeCamel(field.name);
+ code += " Mutate" + namer_.Function(field);
code += "(j int, n " + TypeName(field) + ") bool ";
code += OffsetPrefix(field);
code += "\t\ta := rcv._tab.Vector(o)\n";
@@ -777,6 +892,12 @@ class GoGenerator : public BaseGenerator {
GenStructAccessor(struct_def, field, code_ptr);
GenStructMutator(struct_def, field, code_ptr);
+ // TODO(michaeltle): Support querying fixed struct by key. Currently,
+ // we only support keyed tables.
+ if (!struct_def.fixed && field.key) {
+ GenKeyCompare(struct_def, field, code_ptr);
+ GenLookupByKey(struct_def, field, code_ptr);
+ }
}
// Generate builders
@@ -789,6 +910,79 @@ class GoGenerator : public BaseGenerator {
}
}
+ void GenKeyCompare(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ FLATBUFFERS_ASSERT(struct_def.has_key);
+ FLATBUFFERS_ASSERT(field.key);
+ std::string &code = *code_ptr;
+
+ code += "func " + namer_.Type(struct_def) + "KeyCompare(";
+ code += "o1, o2 flatbuffers.UOffsetT, buf []byte) bool {\n";
+ code += "\tobj1 := &" + namer_.Type(struct_def) + "{}\n";
+ code += "\tobj2 := &" + namer_.Type(struct_def) + "{}\n";
+ code += "\tobj1.Init(buf, flatbuffers.UOffsetT(len(buf))-o1)\n";
+ code += "\tobj2.Init(buf, flatbuffers.UOffsetT(len(buf))-o2)\n";
+ if (IsString(field.value.type)) {
+ code += "\treturn string(obj1." + namer_.Function(field.name) + "()) < ";
+ code += "string(obj2." + namer_.Function(field.name) + "())\n";
+ } else {
+ code += "\treturn obj1." + namer_.Function(field.name) + "() < ";
+ code += "obj2." + namer_.Function(field.name) + "()\n";
+ }
+ code += "}\n\n";
+ }
+
+ void GenLookupByKey(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ FLATBUFFERS_ASSERT(struct_def.has_key);
+ FLATBUFFERS_ASSERT(field.key);
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += " LookupByKey(";
+ code += "key " + NativeType(field.value.type) + ", ";
+ code += "vectorLocation flatbuffers.UOffsetT, ";
+ code += "buf []byte) bool {\n";
+ code += "\tspan := flatbuffers.GetUOffsetT(buf[vectorLocation-4:])\n";
+ code += "\tstart := flatbuffers.UOffsetT(0)\n";
+ if (IsString(field.value.type)) { code += "\tbKey := []byte(key)\n"; }
+ code += "\tfor span != 0 {\n";
+ code += "\t\tmiddle := span / 2\n";
+ code += "\t\ttableOffset := flatbuffers.GetIndirectOffset(buf, ";
+ code += "vectorLocation+4*(start+middle))\n";
+
+ code += "\t\tobj := &" + namer_.Type(struct_def) + "{}\n";
+ code += "\t\tobj.Init(buf, tableOffset)\n";
+
+ if (IsString(field.value.type)) {
+ needs_bytes_import_ = true;
+ code +=
+ "\t\tcomp := bytes.Compare(obj." + namer_.Function(field.name) + "()";
+ code += ", bKey)\n";
+ } else {
+ code += "\t\tval := obj." + namer_.Function(field.name) + "()\n";
+ code += "\t\tcomp := 0\n";
+ code += "\t\tif val > key {\n";
+ code += "\t\t\tcomp = 1\n";
+ code += "\t\t} else if val < key {\n";
+ code += "\t\t\tcomp = -1\n";
+ code += "\t\t}\n";
+ }
+ code += "\t\tif comp > 0 {\n";
+ code += "\t\t\tspan = middle\n";
+ code += "\t\t} else if comp < 0 {\n";
+ code += "\t\t\tmiddle += 1\n";
+ code += "\t\t\tstart += middle\n";
+ code += "\t\t\tspan -= middle\n";
+ code += "\t\t} else {\n";
+ code += "\t\t\trcv.Init(buf, tableOffset)\n";
+ code += "\t\t\treturn true\n";
+ code += "\t\t}\n";
+ code += "\t}\n";
+ code += "\treturn false\n";
+ code += "}\n\n";
+ }
+
void GenNativeStruct(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -801,8 +995,10 @@ class GoGenerator : public BaseGenerator {
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 += "\t" + namer_.Field(field) + " ";
+ if (field.IsScalarOptional()) { code += "*"; }
+ code += NativeType(field.value.type) + " `json:\"" + field.name + "\"`" +
+ "\n";
}
code += "}\n\n";
@@ -818,7 +1014,7 @@ class GoGenerator : public BaseGenerator {
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 += "\tType " + namer_.Type(enum_def) + "\n";
code += "\tValue interface{}\n";
code += "}\n\n";
}
@@ -834,7 +1030,7 @@ class GoGenerator : public BaseGenerator {
++it2) {
const EnumVal &ev = **it2;
if (ev.IsZero()) continue;
- code += "\tcase " + enum_def.name + ev.name + ":\n";
+ code += "\tcase " + namer_.EnumVariant(enum_def, ev) + ":\n";
code += "\t\treturn t.Value.(" + NativeType(ev.union_type) +
").Pack(builder)\n";
}
@@ -846,7 +1042,7 @@ class GoGenerator : public BaseGenerator {
void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func (rcv " + enum_def.name +
+ code += "func (rcv " + namer_.Type(enum_def) +
") UnPack(table flatbuffers.Table) *" + NativeName(enum_def) +
" {\n";
code += "\tswitch rcv {\n";
@@ -855,13 +1051,17 @@ class GoGenerator : public BaseGenerator {
++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 += "\tcase " + namer_.EnumVariant(enum_def, ev) + ":\n";
+ code += "\t\tvar x " +
+ WrapInNameSpaceAndTrack(ev.union_type.struct_def,
+ ev.union_type.struct_def->name) +
+ "\n";
+ code += "\t\tx.Init(table.Bytes, table.Pos)\n";
code += "\t\treturn &" +
- WrapInNameSpaceAndTrack(enum_def.defined_namespace,
- NativeName(enum_def)) +
- "{ Type: " + enum_def.name + ev.name + ", Value: x.UnPack() }\n";
+ WrapInNameSpaceAndTrack(&enum_def, NativeName(enum_def)) +
+ "{Type: " + namer_.EnumVariant(enum_def, ev) +
+ ", Value: x.UnPack()}\n";
}
code += "\t}\n";
code += "\treturn nil\n";
@@ -870,63 +1070,70 @@ class GoGenerator : public BaseGenerator {
void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
+ const std::string struct_type = namer_.Type(struct_def);
code += "func (t *" + NativeName(struct_def) +
") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
- code += "\tif t == nil { return 0 }\n";
+ code += "\tif t == nil {\n\t\treturn 0\n\t}\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";
+ const std::string field_field = namer_.Field(field);
+ const std::string field_var = namer_.Variable(field);
+ const std::string offset = field_var + "Offset";
if (IsString(field.value.type)) {
- code += "\t" + offset + " := builder.CreateString(t." +
- MakeCamel(field.name) + ")\n";
+ code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
+ code += "\tif t." + field_field + " != \"\" {\n";
+ code += "\t\t" + offset + " = builder.CreateString(t." + field_field +
+ ")\n";
+ code += "\t}\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 += "\tif t." + field_field + " != nil {\n";
code += "\t\t" + offset + " = builder.CreateByteString(t." +
- MakeCamel(field.name) + ")\n";
+ field_field + ")\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";
+ code += "\tif t." + field_field + " != nil {\n";
+ std::string length = field_var + "Length";
+ std::string offsets = field_var + "Offsets";
+ code += "\t\t" + length + " := len(t." + field_field + ")\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";
+ field_field + "[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) +
+ code += "\t\t\t" + offsets + "[j] = t." + field_field +
"[j].Pack(builder)\n";
code += "\t\t}\n";
}
- code += "\t\t" + struct_def.name + "Start" + MakeCamel(field.name) +
+ code += "\t\t" + struct_type + "Start" + namer_.Function(field) +
"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())) + "(" +
+ namer_.Method(GenTypeBasic(field.value.type.VectorType())) +
+ "(" +
CastToBaseType(field.value.type.VectorType(),
- "t." + MakeCamel(field.name) + "[j]") +
+ "t." + field_field + "[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";
+ code += "\t\t\tt." + field_field + "[j].Pack(builder)\n";
} else {
code += "\t\t\tbuilder.PrependUOffsetT(" + offsets + "[j])\n";
}
@@ -935,92 +1142,96 @@ class GoGenerator : public BaseGenerator {
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";
+ code += "\t" + offset + " := t." + field_field + ".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";
+ code += "\t" + offset + " := t." + field_field + ".Pack(builder)\n\n";
} else {
FLATBUFFERS_ASSERT(0);
}
}
- code += "\t" + struct_def.name + "Start(builder)\n";
+ code += "\t" + struct_type + "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;
+ const std::string field_field = namer_.Field(field);
+ const std::string field_fn = namer_.Function(field);
+ const std::string offset = namer_.Variable(field) + "Offset";
- std::string offset = MakeCamel(field.name, false) + "Offset";
if (IsScalar(field.value.type.base_type)) {
+ std::string prefix;
+ if (field.IsScalarOptional()) {
+ code += "\tif t." + field_field + " != nil {\n\t";
+ prefix = "*";
+ }
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";
+ code += "\t" + struct_type + "Add" + field_fn + "(builder, " +
+ prefix + "t." + field_field + ")\n";
}
+ if (field.IsScalarOptional()) { code += "\t}\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";
+ code += "\t" + offset + " := t." + field_field + ".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 += "\tif t." + field_field + " != nil {\n";
+ code += "\t\t" + struct_type + "Add" +
+ namer_.Method(field.name + UnionTypeFieldSuffix()) +
+ "(builder, t." + field_field + ".Type)\n";
code += "\t}\n";
}
- code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
- "(builder, " + offset + ")\n";
+ code += "\t" + struct_type + "Add" + field_fn + "(builder, " + offset +
+ ")\n";
}
}
- code += "\treturn " + struct_def.name + "End(builder)\n";
+ code += "\treturn " + struct_type + "End(builder)\n";
code += "}\n\n";
}
void GenNativeTableUnPack(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
+ const std::string struct_type = namer_.Type(struct_def);
- code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
+ code += "func (rcv *" + struct_type + ") 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";
+ const std::string field_field = namer_.Field(field);
+ const std::string field_var = namer_.Variable(field);
+ const std::string length = field_var + "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";
+ code += "\tt." + field_field + " = rcv." + field_field + "()\n";
} else if (IsString(field.value.type)) {
- code += "\tt." + field_name_camel + " = string(rcv." +
- field_name_camel + "())\n";
+ code += "\tt." + field_field + " = string(rcv." + field_field + "())\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";
+ code += "\tt." + field_field + " = rcv." + field_field + "Bytes()\n";
} else if (IsVector(field.value.type)) {
- code += "\t" + length + " := rcv." + field_name_camel + "Length()\n";
- code += "\tt." + field_name_camel + " = make(" +
+ code += "\t" + length + " := rcv." + field_field + "Length()\n";
+ code += "\tt." + field_field + " = 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) +
+ WrapInNameSpaceAndTrack(field.value.type.struct_def,
+ field.value.type.struct_def->name) +
"{}\n";
- code += "\t\trcv." + field_name_camel + "(&x, j)\n";
+ code += "\t\trcv." + field_field + "(&x, j)\n";
}
- code += "\t\tt." + field_name_camel + "[j] = ";
+ code += "\t\tt." + field_field + "[j] = ";
if (IsScalar(field.value.type.element)) {
- code += "rcv." + field_name_camel + "(j)";
+ code += "rcv." + field_field + "(j)";
} else if (field.value.type.element == BASE_TYPE_STRING) {
- code += "string(rcv." + field_name_camel + "(j))";
+ code += "string(rcv." + field_field + "(j))";
} else if (field.value.type.element == BASE_TYPE_STRUCT) {
code += "x.UnPack()";
} else {
@@ -1030,16 +1241,16 @@ class GoGenerator : public BaseGenerator {
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";
+ code +=
+ "\tt." + field_field + " = rcv." + field_field + "(nil).UnPack()\n";
} else if (field.value.type.base_type == BASE_TYPE_UNION) {
- std::string field_table = MakeCamel(field.name, false) + "Table";
+ const std::string field_table = field_var + "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";
+ "\tif rcv." + namer_.Method(field) + "(&" + field_table + ") {\n";
+ code += "\t\tt." + field_field + " = rcv." +
+ namer_.Method(field.name + UnionTypeFieldSuffix()) +
+ "().UnPack(" + field_table + ")\n";
code += "\t}\n";
} else {
FLATBUFFERS_ASSERT(0);
@@ -1047,9 +1258,9 @@ class GoGenerator : public BaseGenerator {
}
code += "}\n\n";
- code += "func (rcv *" + struct_def.name + ") UnPack() *" +
+ code += "func (rcv *" + struct_type + ") UnPack() *" +
NativeName(struct_def) + " {\n";
- code += "\tif rcv == nil { return nil }\n";
+ code += "\tif rcv == nil {\n\t\treturn nil\n\t}\n";
code += "\tt := &" + NativeName(struct_def) + "{}\n";
code += "\trcv.UnPackTo(t)\n";
code += "\treturn t\n";
@@ -1061,8 +1272,8 @@ class GoGenerator : public BaseGenerator {
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";
+ code += "\tif t == nil {\n\t\treturn 0\n\t}\n";
+ code += "\treturn Create" + namer_.Type(struct_def) + "(builder";
StructPackArgs(struct_def, "", code_ptr);
code += ")\n";
code += "}\n";
@@ -1076,10 +1287,10 @@ class GoGenerator : public BaseGenerator {
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(),
+ (nameprefix + namer_.Field(field) + ".").c_str(),
code_ptr);
} else {
- code += std::string(", t.") + nameprefix + MakeCamel(field.name);
+ code += std::string(", t.") + nameprefix + namer_.Field(field);
}
}
}
@@ -1088,24 +1299,24 @@ class GoGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
- code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
+ code += "func (rcv *" + namer_.Type(struct_def) + ") 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";
+ code += "\tt." + namer_.Field(field) + " = rcv." +
+ namer_.Method(field) + "(nil).UnPack()\n";
} else {
- code += "\tt." + MakeCamel(field.name) + " = rcv." +
- MakeCamel(field.name) + "()\n";
+ code += "\tt." + namer_.Field(field) + " = rcv." +
+ namer_.Method(field) + "()\n";
}
}
code += "}\n\n";
- code += "func (rcv *" + struct_def.name + ") UnPack() *" +
+ code += "func (rcv *" + namer_.Type(struct_def) + ") UnPack() *" +
NativeName(struct_def) + " {\n";
- code += "\tif rcv == nil { return nil }\n";
+ code += "\tif rcv == nil {\n\t\treturn nil\n\t}\n";
code += "\tt := &" + NativeName(struct_def) + "{}\n";
code += "\trcv.UnPackTo(t)\n";
code += "\treturn t\n";
@@ -1152,14 +1363,14 @@ class GoGenerator : public BaseGenerator {
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));
+ default: return "rcv._tab.Get" + namer_.Function(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))
+ ? namer_.Method(GenTypeBasic(field.value.type))
: (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
}
@@ -1179,7 +1390,8 @@ class GoGenerator : public BaseGenerator {
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_STRUCT:
+ return WrapInNameSpaceAndTrack(type.struct_def, type.struct_def->name);
case BASE_TYPE_UNION:
// fall through
default: return "*flatbuffers.Table";
@@ -1192,7 +1404,9 @@ class GoGenerator : public BaseGenerator {
}
std::string TypeName(const FieldDef &field) {
- return GenTypeGet(field.value.type);
+ std::string prefix;
+ if (field.IsScalarOptional()) { prefix = "*"; }
+ return prefix + GenTypeGet(field.value.type);
}
// If type is an enum, returns value with a cast to the enum type, otherwise
@@ -1216,21 +1430,37 @@ class GoGenerator : public BaseGenerator {
}
std::string GenConstant(const FieldDef &field) {
+ if (field.IsScalarOptional()) { return "nil"; }
switch (field.value.type.base_type) {
case BASE_TYPE_BOOL:
return field.value.constant == "0" ? "false" : "true";
+ case BASE_TYPE_FLOAT:
+ case BASE_TYPE_DOUBLE: {
+ const std::string float_type =
+ field.value.type.base_type == BASE_TYPE_FLOAT ? "float32"
+ : "float64";
+ if (StringIsFlatbufferNan(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.NaN())";
+ } else if (StringIsFlatbufferPositiveInfinity(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.Inf(1))";
+ } else if (StringIsFlatbufferNegativeInfinity(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.Inf(-1))";
+ }
+ return field.value.constant;
+ }
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 StructDef &struct_def) const {
+ return namer_.ObjectType(struct_def);
}
- std::string NativeName(const EnumDef &enum_def) {
- return parser_.opts.object_prefix + enum_def.name +
- parser_.opts.object_suffix;
+ std::string NativeName(const EnumDef &enum_def) const {
+ return namer_.ObjectType(enum_def);
}
std::string NativeType(const Type &type) {
@@ -1245,11 +1475,11 @@ class GoGenerator : public BaseGenerator {
} else if (IsVector(type)) {
return "[]" + NativeType(type.VectorType());
} else if (type.base_type == BASE_TYPE_STRUCT) {
- return "*" + WrapInNameSpaceAndTrack(type.struct_def->defined_namespace,
+ return "*" + WrapInNameSpaceAndTrack(type.struct_def,
NativeName(*type.struct_def));
} else if (type.base_type == BASE_TYPE_UNION) {
- return "*" + WrapInNameSpaceAndTrack(type.enum_def->defined_namespace,
- NativeName(*type.enum_def));
+ return "*" +
+ WrapInNameSpaceAndTrack(type.enum_def, NativeName(*type.enum_def));
}
FLATBUFFERS_ASSERT(0);
return std::string();
@@ -1264,6 +1494,7 @@ class GoGenerator : public BaseGenerator {
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) {
@@ -1273,26 +1504,47 @@ class GoGenerator : public BaseGenerator {
code += "package " + name_space_name + "\n\n";
if (needs_imports) {
code += "import (\n";
- if (is_enum) { code += "\t\"strconv\"\n\n"; }
+ // standard imports, in alphabetical order for go fmt
+ if (needs_bytes_import_) code += "\t\"bytes\"\n";
if (!parser_.opts.go_import.empty()) {
code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n";
} else {
code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
}
+ // math is needed to support non-finite scalar default values.
+ if (needs_math_import_) { code += "\t\"math\"\n"; }
+ if (is_enum) { code += "\t\"strconv\"\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";
+ if ((*it)->defined_namespace->components.empty()) {
+ code += "\t" + (*it)->name + " \"" + (*it)->name + "\"\n";
+ } else {
+ code += "\t" + NamespaceImportName((*it)->defined_namespace) +
+ " \"" + NamespaceImportPath((*it)->defined_namespace) +
+ "\"\n";
+ }
}
}
code += ")\n\n";
} else {
if (is_enum) { code += "import \"strconv\"\n\n"; }
+ if (needs_math_import_) {
+ // math is needed to support non-finite scalar default values.
+ code += "import \"math\"\n\n";
+ }
}
}
+ // Resets the needed imports before generating a new file.
+ void ResetImports() {
+ tracked_imported_namespaces_.clear();
+ needs_bytes_import_ = false;
+ needs_math_import_ = false;
+ }
+
// 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) {
@@ -1301,56 +1553,45 @@ class GoGenerator : public BaseGenerator {
Namespace &ns = go_namespace_.components.empty() ? *def.defined_namespace
: go_namespace_;
std::string code = "";
- BeginFile(LastNamespacePart(ns), needs_imports, is_enum, &code);
+ BeginFile(ns.components.empty() ? def.name : 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";
+ std::string directory = namer_.Directories(ns);
+ std::string file = namer_.File(def, SkipFile::Suffix);
+ EnsureDirExists(directory);
+ std::string filename = directory + file;
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;
+ std::string NamespaceImportName(const Namespace *ns) const {
+ return namer_.Namespace(*ns);
}
// 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;
- }
+ std::string NamespaceImportPath(const Namespace *ns) const {
+ std::string path =
+ namer_.Directories(*ns, SkipDir::OutputPathAndTrailingPathSeparator);
+ if (!parser_.opts.go_module_name.empty()) {
+ path = parser_.opts.go_module_name + "/" + path;
}
- return s;
+ return path;
}
// 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,
+ std::string WrapInNameSpaceAndTrack(const Definition *def,
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);
+ if (CurrentNameSpace() == def->defined_namespace) return name;
+ tracked_imported_namespaces_.insert(def);
+ if (def->defined_namespace->components.empty())
+ return def->name + "." + name;
+ else
+ return NamespaceImportName(def->defined_namespace) + "." + name;
}
const Namespace *CurrentNameSpace() const { return cur_name_space_; }
@@ -1371,4 +1612,59 @@ bool GenerateGo(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace {
+
+class GoCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateGo(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateGoGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kGo; }
+
+ std::string LanguageName() const override { return "Go"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewGoCodeGenerator() {
+ return std::unique_ptr<GoCodeGenerator>(new GoCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_go.h b/contrib/libs/flatbuffers/src/idl_gen_go.h
new file mode 100644
index 0000000000..d81c1ff650
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_go.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_GO_H_
+#define FLATBUFFERS_IDL_GEN_GO_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Go code generator.
+std::unique_ptr<CodeGenerator> NewGoCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_GO_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp b/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
index 9aea745d4e..2be24e71a2 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
@@ -191,7 +191,7 @@ class FlatBufPrinter : public grpc_generator::Printer {
}
}
- void SetIndentationSize(const int size) {
+ void SetIndentationSize(const size_t size) {
FLATBUFFERS_ASSERT(str_->empty());
indentation_size_ = size;
}
@@ -199,15 +199,15 @@ class FlatBufPrinter : public grpc_generator::Printer {
void Indent() { indent_++; }
void Outdent() {
+ FLATBUFFERS_ASSERT(indent_ > 0);
indent_--;
- FLATBUFFERS_ASSERT(indent_ >= 0);
}
private:
std::string *str_;
char escape_char_;
- int indent_;
- int indentation_size_;
+ size_t indent_;
+ size_t indentation_size_;
char indentation_type_;
};
@@ -242,10 +242,6 @@ class FlatBufFile : public grpc_generator::File {
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("");
}
@@ -345,6 +341,7 @@ bool GenerateGoGRPC(const Parser &parser, const std::string &path,
bool GenerateCppGRPC(const Parser &parser, const std::string &path,
const std::string &file_name) {
+ const auto &opts = parser.opts;
int nservices = 0;
for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
++it) {
@@ -352,9 +349,15 @@ bool GenerateCppGRPC(const Parser &parser, const std::string &path,
}
if (!nservices) return true;
+ std::string suffix = "";
+ suffix += opts.filename_suffix.empty() ? "_generated" : opts.filename_suffix;
+ suffix += ".";
+ suffix += opts.filename_extension.empty() ? "h" : opts.filename_extension;
+
grpc_cpp_generator::Parameters generator_parameters;
// TODO(wvo): make the other parameters in this struct configurable.
generator_parameters.use_system_headers = true;
+ generator_parameters.message_header_extension = suffix;
FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguageCpp);
diff --git a/contrib/libs/flatbuffers/src/idl_gen_java.cpp b/contrib/libs/flatbuffers/src/idl_gen_java.cpp
index cfd3a55cdb..34895ee9dc 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_java.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_java.cpp
@@ -16,34 +16,94 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_java.h"
+
#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)
+#include "idl_namer.h"
namespace flatbuffers {
namespace java {
-static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
+namespace {
+
+static Namer::Config JavaDefaultConfig() {
+ return {
+ /*types=*/Case::kKeep,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/".",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".java",
+ };
+}
+
+static std::set<std::string> JavaKeywords() {
+ return {
+ "abstract", "continue", "for", "new", "switch",
+ "assert", "default", "goto", "package", "synchronized",
+ "boolean", "do", "if", "private", "this",
+ "break", "double", "implements", "protected", "throw",
+ "byte", "else", "import", "public", "throws",
+ "case", "enum", "instanceof", "return", "transient",
+ "catch", "extends", "int", "short", "try",
+ "char", "final", "interface", "static", "void",
+ "class", "finally", "long", "strictfp", "volatile",
+ "const", "float", "native", "super", "while",
+ };
+}
+
+static const TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
"POSITIVE_INFINITY",
"NEGATIVE_INFINITY");
-static CommentConfig comment_config = {
+static const CommentConfig comment_config = {
"/**",
" *",
" */",
};
+} // namespace
+
class JavaGenerator : public BaseGenerator {
+ struct FieldArrayLength {
+ std::string name;
+ int length;
+ };
+
public:
JavaGenerator(const Parser &parser, const std::string &path,
- const std::string &file_name)
+ const std::string &file_name,
+ const std::string &package_prefix)
: BaseGenerator(parser, path, file_name, "", ".", "java"),
- cur_name_space_(nullptr) {}
+ cur_name_space_(nullptr),
+ namer_(WithFlagOptions(JavaDefaultConfig(), parser.opts, path),
+ JavaKeywords()) {
+ if (!package_prefix.empty()) {
+ std::istringstream iss(package_prefix);
+ std::string component;
+ while(std::getline(iss, component, '.')) {
+ package_prefix_ns_.components.push_back(component);
+ }
+ package_prefix_ = package_prefix_ns_.GetFullyQualifiedName("") + ".";
+ }
+ }
JavaGenerator &operator=(const JavaGenerator &);
bool generate() {
@@ -55,7 +115,7 @@ class JavaGenerator : public BaseGenerator {
std::string enumcode;
auto &enum_def = **it;
if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
- GenEnum(enum_def, &enumcode);
+ GenEnum(enum_def, enumcode);
if (parser_.opts.one_file) {
one_file_code += enumcode;
} else {
@@ -63,6 +123,19 @@ class JavaGenerator : public BaseGenerator {
/* needs_includes= */ false))
return false;
}
+
+ if (parser_.opts.generate_object_based_api && enum_def.is_union) {
+ enumcode = "";
+ GenEnum_ObjectAPI(enum_def, enumcode);
+ auto class_name = namer_.Type(enum_def) + "Union";
+ if (parser_.opts.one_file) {
+ one_file_code += enumcode;
+ } else {
+ if (!SaveType(class_name, *enum_def.defined_namespace, enumcode,
+ /* needs_includes= */ false))
+ return false;
+ }
+ }
}
for (auto it = parser_.structs_.vec.begin();
@@ -71,7 +144,7 @@ class JavaGenerator : public BaseGenerator {
auto &struct_def = **it;
if (!parser_.opts.one_file)
cur_name_space_ = struct_def.defined_namespace;
- GenStruct(struct_def, &declcode);
+ GenStruct(struct_def, declcode, parser_.opts);
if (parser_.opts.one_file) {
one_file_code += declcode;
} else {
@@ -79,6 +152,19 @@ class JavaGenerator : public BaseGenerator {
/* needs_includes= */ true))
return false;
}
+
+ if (parser_.opts.generate_object_based_api) {
+ declcode = "";
+ GenStruct_ObjectAPI(struct_def, declcode);
+ auto class_name = namer_.ObjectType(struct_def);
+ if (parser_.opts.one_file) {
+ one_file_code += declcode;
+ } else {
+ if (!SaveType(class_name, *struct_def.defined_namespace, declcode,
+ /* needs_includes= */ true))
+ return false;
+ }
+ }
}
if (parser_.opts.one_file) {
@@ -97,15 +183,35 @@ class JavaGenerator : public BaseGenerator {
std::string code;
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
- std::string namespace_name = FullNamespace(".", ns);
+ Namespace combined_ns = package_prefix_ns_;
+ std::copy(
+ ns.components.begin(),
+ ns.components.end(),
+ std::back_inserter(combined_ns.components));
+
+ const std::string namespace_name = FullNamespace(".", combined_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";
+ "import com.google.flatbuffers.BaseVector;\n"
+ "import com.google.flatbuffers.BooleanVector;\n"
+ "import com.google.flatbuffers.ByteVector;\n"
+ "import com.google.flatbuffers.Constants;\n"
+ "import com.google.flatbuffers.DoubleVector;\n"
+ "import com.google.flatbuffers.FlatBufferBuilder;\n"
+ "import com.google.flatbuffers.FloatVector;\n"
+ "import com.google.flatbuffers.IntVector;\n"
+ "import com.google.flatbuffers.LongVector;\n"
+ "import com.google.flatbuffers.ShortVector;\n"
+ "import com.google.flatbuffers.StringVector;\n"
+ "import com.google.flatbuffers.Struct;\n"
+ "import com.google.flatbuffers.Table;\n"
+ "import com.google.flatbuffers.UnionVector;\n"
+ "import java.nio.ByteBuffer;\n"
+ "import java.nio.ByteOrder;\n";
if (parser_.opts.gen_nullable) {
code += "\nimport javax.annotation.Nullable;\n";
}
@@ -117,7 +223,10 @@ class JavaGenerator : public BaseGenerator {
code += classcode;
if (!namespace_name.empty()) code += "";
- auto filename = NamespaceDir(ns) + defname + ".java";
+ const std::string dirs = namer_.Directories(combined_ns);
+ EnsureDirExists(dirs);
+ const std::string filename =
+ dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix);
return SaveFile(filename.c_str(), code, false);
}
@@ -154,7 +263,8 @@ class JavaGenerator : public BaseGenerator {
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_STRUCT:
+ return Prefixed(namer_.NamespacedType(*type.struct_def));
case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // else fall thru
default: return "Table";
}
@@ -231,11 +341,11 @@ class JavaGenerator : public BaseGenerator {
} else {
if (castFromDest) {
if (type.base_type == BASE_TYPE_UINT)
- return "(int)";
+ return "(int) ";
else if (type.base_type == BASE_TYPE_USHORT)
- return "(short)";
+ return "(short) ";
else if (type.base_type == BASE_TYPE_UCHAR)
- return "(byte)";
+ return "(byte) ";
}
}
return "";
@@ -258,8 +368,9 @@ class JavaGenerator : public BaseGenerator {
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;
+ return
+ enum_val ? Prefixed(namer_.NamespacedEnumVariant(enum_def, *enum_val))
+ : value.constant;
}
std::string GenDefaultValue(const FieldDef &field) const {
@@ -293,8 +404,7 @@ class JavaGenerator : public BaseGenerator {
return GenDefaultValue(field);
}
- void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
- std::string &code = *code_ptr;
+ void GenEnum(EnumDef &enum_def, std::string &code) const {
if (enum_def.generated) return;
// Generate enum definitions of the form:
@@ -302,28 +412,33 @@ class JavaGenerator : public BaseGenerator {
// 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);
+ GenComment(enum_def.doc_comment, &code, &comment_config);
+ code += "@SuppressWarnings(\"unused\")\n";
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 += "final class " + namer_.Type(enum_def);
code += " {\n";
- code += " private " + enum_def.name + "() { }\n";
+ code += " private " + namer_.Type(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, &comment_config, " ");
+ GenComment(ev.doc_comment, &code, &comment_config, " ");
code += " public static final ";
code += GenTypeBasic(DestinationType(enum_def.underlying_type, false));
code += " ";
- code += ev.name + " = ";
+ code += namer_.Variant(ev) + " = ";
code += enum_def.ToString(ev);
+ if (enum_def.underlying_type.base_type == BASE_TYPE_LONG ||
+ enum_def.underlying_type.base_type == BASE_TYPE_ULONG) {
+ code += "L";
+ }
code += ";\n";
}
- // Generate a generate string table for enum values.
+ // Generate a 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.
@@ -331,24 +446,27 @@ class JavaGenerator : public BaseGenerator {
// 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) {
+ if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness &&
+ GenTypeBasic(DestinationType(enum_def.underlying_type, false)) !=
+ "long") {
code += "\n public static final String";
code += "[] names = { ";
- auto val = enum_def.Vals().front();
+ const EnumVal *prev = 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 + "\", ";
+ const EnumVal &ev = **it;
+ for (auto k = enum_def.Distance(prev, &ev); k > 1; --k)
+ code += "\"\", ";
+ prev = &ev;
+ code += "\"" + namer_.Variant(ev) + "\", ";
}
code += "};\n\n";
code += " public static ";
code += "String";
- code += " " + MakeCamel("name", false);
+ code += " name";
code += "(int e) { return names[e";
if (enum_def.MinValue()->IsNonZero())
- code += " - " + enum_def.MinValue()->name;
+ code += " - " + namer_.Variant(enum_def.MinValue()->name);
code += "]; }\n";
}
@@ -369,7 +487,7 @@ class JavaGenerator : public BaseGenerator {
if (type.base_type == BASE_TYPE_BOOL) {
getter = "0!=" + getter;
} else if (GenTypeBasic(type) != "byte") {
- getter += MakeCamel(GenTypeBasic(type));
+ getter += ConvertCase(GenTypeBasic(type), Case::kUpperCamel);
}
return getter;
}
@@ -385,7 +503,7 @@ class JavaGenerator : public BaseGenerator {
auto dest_cast = DestinationCast(type);
auto getter = data_buffer + ".get";
if (GenTypeBasic(type) != "byte") {
- getter += MakeCamel(GenTypeBasic(type));
+ getter += ConvertCase(GenTypeBasic(type), Case::kUpperCamel);
}
getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" +
dest_mask;
@@ -398,7 +516,7 @@ class JavaGenerator : public BaseGenerator {
if (IsScalar(type.base_type)) {
std::string setter = "bb.put";
if (GenTypeBasic(type) != "byte" && type.base_type != BASE_TYPE_BOOL) {
- setter += MakeCamel(GenTypeBasic(type));
+ setter += ConvertCase(GenTypeBasic(type), Case::kUpperCamel);
}
return setter;
} else {
@@ -408,15 +526,15 @@ class JavaGenerator : public BaseGenerator {
// 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");
+ return IsScalar(type.base_type)
+ ? ConvertCase(GenTypeBasic(type), Case::kUpperCamel)
+ : (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,
+ void GenStructArgs(const StructDef &struct_def, std::string &code,
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;
@@ -429,15 +547,15 @@ class JavaGenerator : public BaseGenerator {
// 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,
+ GenStructArgs(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), array_cnt);
} else {
code += ", ";
- code += GenTypeBasic(type);
+ code += GenTypeNameDest(field.value.type);
for (size_t i = 0; i < array_cnt; i++) code += "[]";
code += " ";
code += nameprefix;
- code += MakeCamel(field.name, false);
+ code += namer_.Field(field);
}
}
}
@@ -445,10 +563,9 @@ class JavaGenerator : public BaseGenerator {
// 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,
+ void GenStructBody(const StructDef &struct_def, std::string &code,
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) + ", ";
@@ -462,7 +579,7 @@ class JavaGenerator : public BaseGenerator {
code += NumToString(field.padding) + ");\n";
}
if (IsStruct(field_type)) {
- GenStructBody(*field_type.struct_def, code_ptr,
+ GenStructBody(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), index,
in_array);
} else {
@@ -476,7 +593,7 @@ class JavaGenerator : public BaseGenerator {
in_array = true;
}
if (IsStruct(type)) {
- GenStructBody(*field_type.struct_def, code_ptr,
+ GenStructBody(*field_type.struct_def, code,
(nameprefix + (field.name + "_")).c_str(), index + 1,
in_array);
} else {
@@ -484,7 +601,7 @@ class JavaGenerator : public BaseGenerator {
code += indent + " builder.put";
code += GenMethod(type) + "(";
code += SourceCast(type);
- auto argname = nameprefix + MakeCamel(field.name, false);
+ auto argname = nameprefix + namer_.Variable(field);
code += argname;
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
for (size_t i = 0; in_array && i < array_cnt; i++) {
@@ -497,12 +614,6 @@ class JavaGenerator : public BaseGenerator {
}
}
- 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 = "";
@@ -511,7 +622,7 @@ class JavaGenerator : public BaseGenerator {
key_offset += num;
key_offset += ", _bb)";
} else {
- key_offset += GenByteBufferLength("bb");
+ key_offset += "bb.capacity()";
key_offset += " - tableOffset, bb)";
}
return key_offset;
@@ -560,9 +671,9 @@ class JavaGenerator : public BaseGenerator {
return key_getter;
}
- void GenStruct(StructDef &struct_def, std::string *code_ptr) const {
+ void GenStruct(StructDef &struct_def, std::string &code,
+ 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); }
@@ -570,7 +681,7 @@ class JavaGenerator : public BaseGenerator {
// public type name() {
// int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
// }
- GenComment(struct_def.doc_comment, code_ptr, &comment_config);
+ GenComment(struct_def.doc_comment, &code, &comment_config);
if (parser_.opts.gen_generated) {
code += "@javax.annotation.Generated(value=\"flatc\")\n";
@@ -581,33 +692,35 @@ class JavaGenerator : public BaseGenerator {
} else {
code += "public ";
}
- code += "final class " + struct_def.name;
+ const auto struct_class = namer_.Type(struct_def);
+ code += "final class " + struct_class;
code += " extends ";
code += struct_def.fixed ? "Struct" : "Table";
code += " {\n";
if (!struct_def.fixed) {
- // Generate verson check method.
+ // Generate version 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 += "FLATBUFFERS_23_5_9(); ";
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;
+ const std::string method_name =
+ namer_.LegacyJavaMethod2("getRootAs", struct_def, "");
+ const std::string method_signature =
+ " public static " + struct_class + " " + 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";
+ code +=
+ "{ return " + method_name + "(_bb, new " + struct_class + "()); }\n";
// create method that allows object reuse
code +=
- method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
+ method_signature + "(ByteBuffer _bb, " + struct_class + " obj) { ";
code += "_bb.order(ByteOrder.LITTLE_ENDIAN); ";
code += "return (obj.__assign(_bb.getInt(_bb.";
code += "position()";
@@ -618,8 +731,10 @@ class JavaGenerator : public BaseGenerator {
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 += "boolean " +
+ namer_.LegacyJavaMethod2(
+ "", struct_def, "BufferHasIdentifier(ByteBuffer _bb)") +
+ " { return ";
code += "__has_identifier(_bb, \"";
code += parser_.file_identifier_;
code += "\"); }\n";
@@ -632,27 +747,24 @@ class JavaGenerator : public BaseGenerator {
code += "{ ";
code += "__reset(_i, _bb); ";
code += "}\n";
- code +=
- " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+ code += " public " + struct_class + " __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 =
+ GenComment(field.doc_comment, &code, &comment_config, " ");
+ const std::string type_name = GenTypeGet(field.value.type);
+ const std::string type_name_dest = GenTypeNameDest(field.value.type);
+ const std::string dest_mask = DestinationMask(field.value.type, true);
+ const std::string dest_cast = DestinationCast(field.value.type);
+ const std::string src_cast = SourceCast(field.value.type);
+ const 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";
+ GenPureAnnotation(field.value.type) + type_name_dest + " " +
+ namer_.Field(field);
+ const std::string obj = "obj";
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that:
@@ -665,22 +777,21 @@ class JavaGenerator : public BaseGenerator {
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 += namer_.Field(field);
code += "(new ";
code += type_name + "()); }\n";
- } else if (IsVector(field.value.type) &&
+ } else if (IsSeries(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 += namer_.Field(field);
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 += "()";
@@ -693,7 +804,7 @@ class JavaGenerator : public BaseGenerator {
} else {
code += offset_prefix + getter;
code += "(o + bb_pos)" + dest_mask;
- code += " : " + default_cast;
+ code += " : ";
code += GenDefaultValue(field);
}
} else {
@@ -705,7 +816,7 @@ class JavaGenerator : public BaseGenerator {
code += "bb_pos + " + NumToString(field.value.offset) + ", ";
code += "bb)";
} else {
- code += offset_prefix + conditional_cast;
+ code += offset_prefix;
code += obj + ".__assign(";
code += field.value.type.struct_def->fixed
? "o + bb_pos"
@@ -730,7 +841,7 @@ class JavaGenerator : public BaseGenerator {
code += type_name + " obj, ";
}
code += "int j)";
- const auto body = offset_prefix + conditional_cast + getter + "(";
+ const auto body = offset_prefix + getter + "(";
if (vectortype.base_type == BASE_TYPE_UNION) {
code += body + "obj, ";
} else {
@@ -754,11 +865,9 @@ class JavaGenerator : public BaseGenerator {
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");
+ code += field.value.type.element == BASE_TYPE_BOOL
+ ? "false"
+ : (IsScalar(field.value.type.element) ? "0" : "null");
}
break;
@@ -773,7 +882,7 @@ class JavaGenerator : public BaseGenerator {
code += member_suffix;
code += "}\n";
if (IsVector(field.value.type)) {
- code += " public int " + MakeCamel(field.name, false);
+ code += " public int " + namer_.Field(field);
code += "Length";
code += "()";
code += offset_prefix;
@@ -788,9 +897,9 @@ class JavaGenerator : public BaseGenerator {
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
auto &key_field = **kit;
if (key_field.key) {
- auto qualified_name = WrapInNameSpace(sd);
+ auto qualified_name = Prefixed(namer_.NamespacedType(sd));
code += " public " + qualified_name + " ";
- code += MakeCamel(field.name, false) + "ByKey(";
+ code += namer_.Method(field) + "ByKey(";
code += GenTypeNameDest(key_field.value.type) + " key)";
code += offset_prefix;
code += qualified_name + ".__lookup_by_key(";
@@ -799,7 +908,7 @@ class JavaGenerator : public BaseGenerator {
code += "bb) : null; ";
code += "}\n";
code += " public " + qualified_name + " ";
- code += MakeCamel(field.name, false) + "ByKey(";
+ code += namer_.Method(field) + "ByKey(";
code += qualified_name + " obj, ";
code += GenTypeNameDest(key_field.value.type) + " key)";
code += offset_prefix;
@@ -817,7 +926,8 @@ class JavaGenerator : public BaseGenerator {
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";
+ vector_type_name =
+ ConvertCase(type_name, Case::kUpperCamel) + "Vector";
} else if (element_base_type == BASE_TYPE_STRING) {
vector_type_name = "StringVector";
} else if (element_base_type == BASE_TYPE_UNION) {
@@ -826,14 +936,13 @@ class JavaGenerator : public BaseGenerator {
vector_type_name = type_name + ".Vector";
}
auto vector_method_start = GenNullableAnnotation(field.value.type) +
- " public " + vector_type_name + optional +
- " " + MakeCamel(field.name, false) +
- "Vector";
+ " public " + vector_type_name + " " +
+ namer_.Field(field, "vector");
code += vector_method_start + "() { return ";
- code += MakeCamel(field.name, false) + "Vector";
+ code += namer_.Field(field, "vector");
code += "(new " + vector_type_name + "()); }\n";
code += vector_method_start + "(" + vector_type_name + " obj)";
- code += offset_prefix + conditional_cast + obj + ".__assign(";
+ code += offset_prefix + obj + ".__assign(";
code += "__vector(o), ";
if (!IsScalar(element_base_type)) {
auto vectortype = field.value.type.VectorType();
@@ -846,7 +955,7 @@ class JavaGenerator : public BaseGenerator {
IsScalar(field.value.type.VectorType().base_type)) ||
IsString(field.value.type)) {
code += " public ByteBuffer ";
- code += MakeCamel(field.name, false);
+ code += namer_.Field(field);
code += "AsByteBuffer() { return ";
code += "__vector_as_bytebuffer(";
code += NumToString(field.value.offset) + ", ";
@@ -855,7 +964,7 @@ class JavaGenerator : public BaseGenerator {
: InlineSize(field.value.type.VectorType()));
code += "); }\n";
code += " public ByteBuffer ";
- code += MakeCamel(field.name, false);
+ code += namer_.Field(field);
code += "InByteBuffer(ByteBuffer _bb) { return ";
code += "__vector_in_bytebuffer(_bb, ";
code += NumToString(field.value.offset) + ", ";
@@ -866,9 +975,10 @@ class JavaGenerator : public BaseGenerator {
}
// generate object accessors if is nested_flatbuffer
if (field.nested_flatbuffer) {
- auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
+ auto nested_type_name =
+ Prefixed(namer_.NamespacedType(*field.nested_flatbuffer));
auto nested_method_name =
- MakeCamel(field.name, false) + "As" + field.nested_flatbuffer->name;
+ namer_.Field(field) + "As" + field.nested_flatbuffer->name;
auto get_nested_method_name = nested_method_name;
code += " public " + nested_type_name + " ";
code += nested_method_name + "() { return ";
@@ -879,7 +989,7 @@ class JavaGenerator : public BaseGenerator {
code += nested_type_name + " obj";
code += ") { int o = __offset(";
code += NumToString(field.value.offset) + "); ";
- code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+ code += "return o != 0 ? " + obj + ".__assign(";
code += "";
code += "__indirect(__vector(o)), ";
code += "bb) : null; }\n";
@@ -894,7 +1004,6 @@ class JavaGenerator : public BaseGenerator {
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, " : "(") +
@@ -912,7 +1021,7 @@ class JavaGenerator : public BaseGenerator {
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 += namer_.Method("mutate", field);
code += mutator_params;
if (struct_def.fixed) {
code += GenSetter(underlying_type) + "(" + setter_index + ", ";
@@ -929,7 +1038,7 @@ class JavaGenerator : public BaseGenerator {
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) + " = " +
+ namer_.Constant(field) + " = " +
NumToString(field.value.offset) + ";";
code += vt_offset_constant;
@@ -937,15 +1046,18 @@ class JavaGenerator : public BaseGenerator {
}
}
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() + " ";
code += "create";
- code += struct_def.name + "(FlatBufferBuilder builder";
- GenStructArgs(struct_def, code_ptr, "");
+ code += struct_class + "(FlatBufferBuilder builder";
+ GenStructArgs(struct_def, code, "");
code += ") {\n";
- GenStructBody(struct_def, code_ptr, "");
+ GenStructBody(struct_def, code, "");
code += " return ";
code += GenOffsetConstruct("builder." + std::string("offset()"));
code += ";\n }\n";
@@ -968,19 +1080,21 @@ class JavaGenerator : public BaseGenerator {
// 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) {
+ struct_has_create = true;
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
code += " public static " + GenOffsetType() + " ";
- code += "create" + struct_def.name;
+ code += namer_.LegacyJavaMethod2("create", struct_def, "");
code += "(FlatBufferBuilder builder";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
+ auto field_name = namer_.Field(field);
if (field.deprecated) continue;
code += ",\n ";
code += GenTypeBasic(DestinationType(field.value.type, false));
code += " ";
- code += field.name;
+ code += field_name;
if (!IsScalar(field.value.type.base_type)) code += "Offset";
}
code += ") {\n builder.";
@@ -991,19 +1105,19 @@ class JavaGenerator : public BaseGenerator {
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
+ auto field_name = namer_.Field(field);
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;
+ code += " " + struct_class + ".";
+ code += namer_.Method("add", field) + "(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 += " return " + struct_class + ".";
+ code += namer_.LegacyJavaMethod2("end", struct_def, "");
code += "(builder);\n }\n\n";
}
// Generate a set of static methods that allow table construction,
@@ -1012,7 +1126,7 @@ class JavaGenerator : public BaseGenerator {
// { builder.addShort(id, name, default); }
// Unlike the Create function, these always work.
code += " public static void start";
- code += struct_def.name;
+ code += struct_class;
code += "(FlatBufferBuilder builder) { builder.";
code += "startTable(";
code += NumToString(struct_def.fields.vec.size()) + "); }\n";
@@ -1020,48 +1134,59 @@ class JavaGenerator : public BaseGenerator {
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 += " public static void " + namer_.Method("add", field);
code += "(FlatBufferBuilder builder, ";
code += GenTypeBasic(DestinationType(field.value.type, false));
- auto argname = MakeCamel(field.name, false);
+ auto argname = namer_.Field(field);
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 (field.key) {
+ // field has key attribute, so always need to exist
+ // even if its value is equal to default.
+ // Generated code will bypass default checking
+ // resulting in { builder.addShort(name); slot(id); }
+ key_field = &field;
+ code += SourceCastBasic(field.value.type);
+ code += argname;
+ code += "); builder.slot(" +
+ NumToString(it - struct_def.fields.vec.begin()) + "); }\n";
+ } else {
+ 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)) {
+ field_has_create_set.insert(&field);
// 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 += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, byte[] data) ";
code += "{ return builder.createByteVector(data); }\n";
code += " public static " + GenVectorOffsetType() + " ";
- code += "create";
- code += MakeCamel(field.name);
+ code += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, ByteBuffer data) ";
code += "{ return builder.createByteVector(data); }\n";
} else {
code += " public static " + GenVectorOffsetType() + " ";
- code += "create";
- code += MakeCamel(field.name);
+ code += namer_.Method("create", field);
code += "Vector(FlatBufferBuilder builder, ";
- code += GenTypeBasic(vector_type) + "[] data) ";
+ code += GenTypeBasic(DestinationType(vector_type, false)) +
+ "[] data) ";
code += "{ builder.startVector(";
code += NumToString(elem_size);
code += ", data.length, ";
@@ -1071,7 +1196,7 @@ class JavaGenerator : public BaseGenerator {
code += "add";
code += GenMethod(vector_type);
code += "(";
- code += SourceCastBasic(vector_type, false);
+ code += SourceCastBasic(vector_type);
code += "data[i]";
code += "); return ";
code += "builder.endVector(); }\n";
@@ -1079,8 +1204,7 @@ class JavaGenerator : public BaseGenerator {
}
// Generate a method to start a vector, data to be added manually
// after.
- code += " public static void start";
- code += MakeCamel(field.name);
+ code += " public static void " + namer_.Method("start", field);
code += "Vector(FlatBufferBuilder builder, int numElems) ";
code += "{ builder.startVector(";
code += NumToString(elem_size);
@@ -1089,7 +1213,7 @@ class JavaGenerator : public BaseGenerator {
}
}
code += " public static " + GenOffsetType() + " ";
- code += "end" + struct_def.name;
+ code += namer_.LegacyJavaMethod2("end", struct_def, "");
code += "(FlatBufferBuilder builder) {\n int o = builder.";
code += "endTable();\n";
for (auto it = struct_def.fields.vec.begin();
@@ -1106,8 +1230,9 @@ class JavaGenerator : public BaseGenerator {
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 += namer_.LegacyJavaMethod2("finish" + size_prefix[i],
+ struct_def, "Buffer");
+ code += "(FlatBufferBuilder builder, " + GenOffsetType();
code += " offset) {";
code += " builder.finish" + size_prefix[i] + "(offset";
@@ -1126,9 +1251,9 @@ class JavaGenerator : public BaseGenerator {
code += GenKeyGetter(key_field);
code += " }\n";
- code += "\n public static " + struct_def.name;
+ code += "\n public static " + struct_class;
code += " __lookup_by_key(";
- code += struct_def.name + " obj, ";
+ code += struct_class + " obj, ";
code += "int vectorLocation, ";
code += GenTypeNameDest(key_field->value.type);
code += " key, ByteBuffer bb) {\n";
@@ -1150,27 +1275,28 @@ class JavaGenerator : public BaseGenerator {
code += " span -= middle;\n";
code += " } else {\n";
code += " return ";
- code += "(obj == null ? new " + struct_def.name + "() : obj)";
+ code += "(obj == null ? new " + struct_class + "() : obj)";
code += ".__assign(tableOffset, bb);\n";
code += " }\n }\n";
code += " return null;\n";
code += " }\n";
}
- GenVectorAccessObject(struct_def, code_ptr);
- code += "}";
- code += "\n\n";
+ GenVectorAccessObject(struct_def, code);
+ if (opts.generate_object_based_api) {
+ GenPackUnPack_ObjectAPI(struct_def, code, opts, struct_has_create,
+ field_has_create_set);
+ }
+ code += "}\n\n";
}
std::string GenOptionalScalarCheck(FieldDef &field) const {
if (!field.IsScalarOptional()) return "";
- return " public boolean has" + MakeCamel(field.name, true) +
+ return " public boolean " + namer_.Method("has", field) +
"() { return 0 != __offset(" + NumToString(field.value.offset) +
"); }\n";
}
- void GenVectorAccessObject(StructDef &struct_def,
- std::string *code_ptr) const {
- auto &code = *code_ptr;
+ void GenVectorAccessObject(StructDef &struct_def, std::string &code) const {
// Generate a vector of structs accessor class.
code += "\n";
code += " ";
@@ -1187,7 +1313,7 @@ class JavaGenerator : public BaseGenerator {
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 type_name = namer_.Type(struct_def);
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";
@@ -1229,16 +1355,904 @@ class JavaGenerator : public BaseGenerator {
code += " }\n";
}
+ void GenEnum_ObjectAPI(EnumDef &enum_def, std::string &code) const {
+ if (enum_def.generated) return;
+ code += "import com.google.flatbuffers.FlatBufferBuilder;\n\n";
+
+ if (!enum_def.attributes.Lookup("private")) { code += "public "; }
+ auto union_name = namer_.Type(enum_def) + "Union";
+ auto union_type =
+ GenTypeBasic(DestinationType(enum_def.underlying_type, false));
+ code += "class " + union_name + " {\n";
+ // Type
+ code += " private " + union_type + " type;\n";
+ // Value
+ code += " private Object value;\n";
+ code += "\n";
+ // getters and setters
+ code += " public " + union_type + " getType() { return type; }\n\n";
+ code += " public void setType(" + union_type +
+ " type) { this.type = type; }\n\n";
+ code += " public Object getValue() { return value; }\n\n";
+ code += " public void setValue(Object value) { this.value = value; }\n\n";
+ // Constructor
+ code += " public " + union_name + "() {\n";
+ code +=
+ " this.type = " + namer_.EnumVariant(enum_def, *enum_def.Vals()[0]) +
+ ";\n";
+ code += " this.value = null;\n";
+ code += " }\n\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, false, true);
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
+ ev.union_type.struct_def->attributes.Lookup("private")) {
+ code += " ";
+ } else {
+ code += " public ";
+ }
+ code += type_name + " as" + ev.name + "() { return (" + type_name +
+ ") value; }\n";
+ }
+ code += "\n";
+ // pack()
+ code += " public static int pack(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) {
+ continue;
+ } else {
+ code += " case " + namer_.EnumVariant(enum_def, ev) + ": return ";
+ if (IsString(ev.union_type)) {
+ code += "builder.createString(_o.as" + ev.name + "());\n";
+ } else {
+ code += GenTypeGet(ev.union_type) + ".pack(builder, _o.as" + ev.name +
+ "());\n";
+ }
+ }
+ }
+ code += " default: return 0;\n";
+ code += " }\n";
+ code += " }\n";
+ code += "}\n\n";
+ }
+
+ void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string &code,
+ const std::string &type_name,
+ const std::string &field_name,
+ bool is_vector) const {
+ const std::string variable_type =
+ is_vector ? type_name.substr(0, type_name.length() - 2) : type_name;
+ const std::string variable_name =
+ "_" + namer_.Variable("o", field_name) + (is_vector ? "Element" : "");
+ const std::string type_params = is_vector ? "_j" : "";
+ const std::string value_params = is_vector ? ", _j" : "";
+ const std::string indent = (is_vector ? " " : " ");
+
+ code += indent + variable_type + " " + variable_name + " = new " +
+ variable_type + "();\n";
+ code += indent +
+ GenTypeBasic(DestinationType(enum_def.underlying_type, false)) +
+ " " + variable_name + "Type = " + field_name + "Type(" +
+ type_params + ");\n";
+ code += indent + variable_name + ".setType(" + variable_name + "Type);\n";
+ code += indent + "Table " + variable_name + "Value;\n";
+ code += indent + "switch (" + variable_name + "Type) {\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) {
+ continue;
+ } else {
+ if (ev.union_type.base_type == BASE_TYPE_STRING ||
+ (ev.union_type.base_type == BASE_TYPE_STRUCT &&
+ ev.union_type.struct_def->fixed)) {
+ continue; // This branch is due to bad implemantation of Unions in
+ // Java which doesn't handle non Table types. Should be
+ // deleted when issue #6561 is fixed.
+ }
+ code += indent + " case " +
+ Prefixed(namer_.NamespacedEnumVariant(enum_def, ev)) + ":\n";
+ auto actual_type = GenTypeGet(ev.union_type);
+ code += indent + " " + variable_name + "Value = " + field_name +
+ "(new " + actual_type + "()" + value_params + ");\n";
+ code += indent + " " + variable_name + ".setValue(" + variable_name +
+ "Value != null ? ((" + actual_type + ") " + variable_name +
+ "Value).unpack() : null);\n";
+ code += indent + " break;\n";
+ }
+ }
+ code += indent + " default: break;\n";
+ code += indent + "}\n";
+ if (is_vector) {
+ code += indent + "_" + namer_.Variable("o", field_name) +
+ "[_j] = " + variable_name + ";\n";
+ }
+ }
+
+ void GenPackUnPack_ObjectAPI(
+ StructDef &struct_def, std::string &code, const IDLOptions &opts,
+ bool struct_has_create,
+ const std::set<FieldDef *> &field_has_create) const {
+ auto struct_name = namer_.ObjectType(struct_def);
+ // unpack()
+ code += " public " + struct_name + " unpack() {\n";
+ code += " " + struct_name + " _o = new " + struct_name + "();\n";
+ code += " 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) {
+ const 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;
+ const auto accessor = namer_.Method(field);
+ const auto variable = "_" + namer_.Variable("o", field);
+ const auto get_field = namer_.Method("get", field);
+ const auto set_field = namer_.Method("set", field);
+
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
+ if (field.IsScalarOptional())
+ type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
+ auto start = " " + type_name + " " + variable + " = ";
+ auto call_setter = true;
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ auto fixed = struct_def.fixed && field.value.type.struct_def->fixed;
+ if (fixed) {
+ code +=
+ " " + accessor + "().unpackTo(_o." + get_field + "());\n";
+ } else {
+ code += " if (" + accessor + "() != null) ";
+ if (field.value.type.struct_def->fixed) {
+ code += accessor + "().unpackTo(_o." + get_field + "());\n";
+ } else {
+ code += "_o." + set_field + "(" + accessor + "().unpack());\n";
+ }
+ code += " else _o." + set_field + "(null);\n";
+ }
+ call_setter = false;
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ auto length_str = NumToString(field.value.type.fixed_length);
+ auto unpack_method =
+ field.value.type.struct_def == nullptr ? "" : ".unpack()";
+ code += start + "_o." + get_field + "();\n";
+ code += " for (int _j = 0; _j < " + length_str + "; ++_j) { " +
+ variable + "[_j] = " + accessor + "(_j)" + unpack_method +
+ "; }\n";
+ call_setter = false;
+ break;
+ }
+ case BASE_TYPE_VECTOR:
+ if (field.value.type.element == BASE_TYPE_UNION) {
+ code += start + "new " +
+ GenConcreteTypeGet_ObjectAPI(field.value.type)
+ .substr(0, type_name.length() - 1) +
+ accessor + "Length()];\n";
+ code +=
+ " for (int _j = 0; _j < " + accessor + "Length(); ++_j) {\n";
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code,
+ type_name, accessor, true);
+ code += " }\n";
+ } else if (field.value.type.element != BASE_TYPE_UTYPE) {
+ auto fixed = field.value.type.struct_def == nullptr;
+ const auto length_accessor = namer_.Method(field, "length");
+ code += start + "new " +
+ GenConcreteTypeGet_ObjectAPI(field.value.type)
+ .substr(0, type_name.length() - 1) +
+ length_accessor + "()];\n";
+ code +=
+ " for (int _j = 0; _j < " + length_accessor + "(); ++_j) {";
+ code += variable + "[_j] = ";
+ if (fixed) {
+ code += accessor + "(_j)";
+ } else {
+ code += "(" + accessor + "(_j) != null ? " + accessor +
+ "(_j).unpack() : null)";
+ }
+ code += ";}\n";
+ }
+ break;
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_UNION: {
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code, type_name,
+ accessor, false);
+ break;
+ }
+ default: {
+ if (field.IsScalarOptional()) {
+ code += start + namer_.Method("has", field) + "() ? " + accessor +
+ "() : null;\n";
+ } else {
+ code += start + accessor + "();\n";
+ }
+ break;
+ }
+ }
+ if (call_setter) {
+ code += " _o." + set_field + "(" + variable + ");\n";
+ }
+ }
+ code += " }\n";
+ // pack()
+ code += " public static " + GenOffsetType() +
+ " pack(FlatBufferBuilder builder, " + struct_name + " _o) {\n";
+ code += " if (_o == null) return 0;\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 = namer_.Field(field);
+ const auto variable = "_" + namer_.Variable("o", field);
+ const auto get_field = namer_.Method("get", field);
+ // pre
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code += " " + GenOffsetType() + " _" + namer_.Variable(field) +
+ " = _o." + get_field +
+ "() == null ? 0 : " + GenTypeGet(field.value.type) +
+ ".pack(builder, _o." + get_field + "());\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,
+ array_lengths, code);
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code += " int _" + field_name + " = _o." + get_field +
+ "() == null ? 0 : "
+ "builder.createString(_o." +
+ get_field + "());\n";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ if (field_has_create.find(&field) != field_has_create.end()) {
+ auto property_name = field_name;
+ auto gen_for_loop = true;
+ std::string array_name = "__" + field_name;
+ std::string array_type = "";
+ std::string element_type = "";
+ std::string to_array = "";
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRING: {
+ array_type = "int";
+ element_type = "String";
+ to_array = "builder.createString(_e)";
+ break;
+ }
+ case BASE_TYPE_STRUCT:
+ array_type = "int";
+ element_type =
+ GenTypeGet_ObjectAPI(field.value.type, true, true);
+ ;
+ to_array = GenTypeGet(field.value.type) + ".pack(builder, _e)";
+ break;
+ case BASE_TYPE_UTYPE:
+ property_name = field_name.substr(0, field_name.size() - 4);
+ array_type = GenTypeBasic(DestinationType(
+ field.value.type.enum_def->underlying_type, false));
+ element_type = field.value.type.enum_def->name + "Union";
+ to_array = "_o." + namer_.Method("get", property_name) +
+ "()[_j].getType()";
+ break;
+ case BASE_TYPE_UNION:
+ array_type = "int";
+ element_type =
+ Prefixed(namer_.NamespacedType(*field.value.type.enum_def))
+ + "Union";
+ to_array = element_type + ".pack(builder, _o." +
+ namer_.Method("get", property_name) + "()[_j])";
+ break;
+ case BASE_TYPE_UCHAR: // TODO this branch of the switch is due to
+ // inconsistent behavior in unsigned byte.
+ // Read further at Issue #6574.
+ array_type = "byte";
+ element_type = "int";
+ to_array = "(byte) _e";
+ break;
+ default:
+ gen_for_loop = false;
+ array_name = "_o." + namer_.Method("get", property_name) + "()";
+ array_type = GenTypeNameDest(field.value.type);
+ element_type = array_type;
+ to_array = "_e";
+ break;
+ }
+ code += " int _" + field_name + " = 0;\n";
+ code += " if (_o." + namer_.Method("get", property_name) +
+ "() != null) {\n";
+ if (gen_for_loop) {
+ code += " " + array_type + "[] " + array_name + " = new " +
+ array_type + "[_o." +
+ namer_.Method("get", property_name) + "().length];\n";
+ code += " int _j = 0;\n";
+ code += " for (" + element_type + " _e : _o." +
+ namer_.Method("get", property_name) + "()) { ";
+ code += array_name + "[_j] = " + to_array + "; _j++;}\n";
+ }
+ code += " _" + field_name + " = " +
+ namer_.Method("create", field) + "Vector(builder, " +
+ array_name + ");\n";
+ code += " }\n";
+ } else {
+ auto type_name = GenTypeGet(field.value.type);
+ auto element_type_name =
+ GenTypeGet_ObjectAPI(field.value.type, true, true);
+ auto pack_method =
+ field.value.type.struct_def == nullptr
+ ? "builder.add" + GenMethod(field.value.type.VectorType()) +
+ "(" + variable + "[_j]);"
+ : "_unused_offset = " + type_name + ".pack(builder, " +
+ variable + "[_j]);";
+ code += " int _" + field_name + " = 0;\n";
+ code += " " + element_type_name + "[] " + variable + " = _o." +
+ get_field + "();\n";
+ code += " if (" + variable + " != null) {\n";
+ if (field.value.type.struct_def != nullptr) {
+ code += " int _unused_offset = 0;\n";
+ }
+ code += " " + namer_.Method("start", field) +
+ "Vector(builder, " + variable + ".length);\n";
+ code += " for (int _j = " + variable +
+ ".length - 1; _j >=0; _j--) { ";
+ code += 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,
+ array_lengths, code);
+ } else {
+ code += " " +
+ GenTypeGet_ObjectAPI(field.value.type, false, true) + " _" +
+ field_name + " = _o." + get_field + "();\n";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code += " " +
+ GenTypeBasic(DestinationType(
+ field.value.type.enum_def->underlying_type, false)) +
+ " _" + field_name + "Type = _o." + get_field +
+ "() == null ? " +
+ Prefixed(namer_.NamespacedType(*field.value.type.enum_def)) +
+ ".NONE : " + "_o." + get_field + "().getType();\n";
+ code += " " + GenOffsetType() + " _" + field_name + " = _o." +
+ get_field + "() == null ? 0 : " +
+ Prefixed(namer_.NamespacedType(*field.value.type.enum_def)) +
+ "Union.pack(builder, _o." + get_field + "());\n";
+ break;
+ }
+ default: break;
+ }
+ }
+ if (struct_has_create) {
+ // Create
+ code += " return " +
+ namer_.LegacyJavaMethod2("create", struct_def, "") + "(\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;
+ const auto field_name = namer_.Field(field);
+ const auto get_field = namer_.Method("get", field);
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (struct_def.fixed) {
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def, code,
+ " _" + field_name + "_");
+ } else {
+ code += ",\n";
+ if (field.value.type.struct_def->fixed) {
+ if (opts.generate_object_based_api)
+ code += " _o." + field_name;
+ else
+ // Seems like unreachable code
+ code += " " + GenTypeGet(field.value.type) +
+ ".Pack(builder, _o." + field_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,
+ " _" + 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." + get_field + "()";
+ break;
+ }
+ }
+ code += ");\n";
+ } else {
+ // Start, End
+ code += " " + namer_.LegacyJavaMethod2("start", struct_def, "") +
+ "(builder);\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 arg = "_" + namer_.Variable(field);
+ const auto get_field = namer_.Method("get", field);
+ const auto add_field = namer_.Method("add", field);
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (field.value.type.struct_def->fixed) {
+ code += " " + add_field + "(builder, " +
+ GenTypeGet(field.value.type) + ".pack(builder, _o." +
+ get_field + "()));\n";
+ } else {
+ code += " " + add_field + "(builder, " + arg + ");\n";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ code += " " + add_field + "(builder, " + arg + ");\n";
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_UNION: {
+ code += " " + add_field + "Type(builder, " + arg + "Type);\n";
+ code += " " + add_field + "(builder, " + arg + ");\n";
+ break;
+ }
+ // scalar
+ default: {
+ if (field.IsScalarOptional()) {
+ code += " if (_o." + get_field + "() != null) { " + add_field +
+ "(builder, _o." + get_field + "()); }\n";
+ } else {
+ code +=
+ " " + add_field + "(builder, _o." + get_field + "());\n";
+ }
+ break;
+ }
+ }
+ }
+ code += " return " + namer_.LegacyJavaMethod2("end", struct_def, "") +
+ "(builder);\n";
+ }
+ code += " }\n";
+ }
+
+ void GenStructPackDecl_ObjectAPI(const StructDef &struct_def,
+ std::vector<FieldArrayLength> &array_lengths,
+ std::string &code) const {
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ const bool is_array = IsArray(field.value.type);
+ const Type &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, array_lengths,
+ code);
+ } 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 += "_" + namer_.Variable(array_lengths[i].name);
+ }
+ code += " " + GenTypeBasic(field_type);
+ if (array_only_lengths.size() > 0) {
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ code += "[]";
+ }
+ code += " " + name + " = ";
+ 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 (int " + 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 += "." + namer_.Method("get", 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 += " " + name + " = ";
+ code += SourceCast(field_type);
+ code += "_o";
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ code += "." + namer_.Method("get", array_lengths[i].name) + "()";
+ }
+ code += ";";
+ }
+ code += "\n";
+ }
+ array_lengths.pop_back();
+ }
+ }
+
+ void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
+ std::string &code,
+ std::string prefix) const {
+ 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,
+ prefix + namer_.Field(field) + "_");
+ } else {
+ code += ",\n";
+ code += prefix + namer_.Field(field);
+ }
+ }
+ }
+
+ std::string ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(
+ const std::string &type_name) const {
+ if (type_name == "boolean")
+ return "Boolean";
+ else if (type_name == "byte")
+ return "Byte";
+ else if (type_name == "char")
+ return "Character";
+ else if (type_name == "short")
+ return "Short";
+ else if (type_name == "int")
+ return "Integer";
+ else if (type_name == "long")
+ return "Long";
+ else if (type_name == "float")
+ return "Float";
+ else if (type_name == "double")
+ return "Double";
+ return type_name;
+ }
+
+ std::string GenTypeGet_ObjectAPI(const flatbuffers::Type &type,
+ bool vectorelem,
+ bool wrap_in_namespace) const {
+ auto type_name = GenTypeNameDest(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 = namer_.ObjectType(*type.struct_def);
+ type_name.replace(type_name.length() - type_name_length,
+ type_name_length, new_type_name);
+ } else if (type.element == BASE_TYPE_UNION) {
+ if (wrap_in_namespace) {
+ type_name =
+ Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
+ } else {
+ type_name = namer_.Type(*type.enum_def) + "Union";
+ }
+ }
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ if (wrap_in_namespace) {
+ type_name =
+ Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
+ } else {
+ type_name = namer_.Type(*type.enum_def) + "Union";
+ }
+ break;
+ }
+ default: break;
+ }
+ if (vectorelem) { return type_name; }
+ switch (type.base_type) {
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ type_name = type_name + "[]";
+ break;
+ }
+ default: break;
+ }
+ return type_name;
+ }
+
+ std::string GenConcreteTypeGet_ObjectAPI(
+ const flatbuffers::Type &type) const {
+ auto type_name = GenTypeNameDest(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 = namer_.ObjectType(*type.struct_def);
+ type_name.replace(type_name.length() - type_name_length,
+ type_name_length, new_type_name);
+ } else if (type.element == BASE_TYPE_UNION) {
+ type_name =
+ Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
+ }
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ type_name =
+ Prefixed(namer_.NamespacedType(*type.enum_def)) + "Union";
+ break;
+ }
+ default: break;
+ }
+
+ switch (type.base_type) {
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ type_name = type_name + "[]";
+ break;
+ }
+ default: break;
+ }
+ return type_name;
+ }
+
+ void GenStruct_ObjectAPI(const StructDef &struct_def,
+ std::string &code) const {
+ if (struct_def.generated) return;
+ if (struct_def.attributes.Lookup("private")) {
+ // For Java, we leave the enum unmarked to indicate package-private
+ } else {
+ code += "public ";
+ }
+
+ const auto class_name = namer_.ObjectType(struct_def);
+ code += "class " + class_name;
+ code += " {\n";
+ // Generate Properties
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const 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, false, true);
+ if (field.IsScalarOptional())
+ type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
+ const auto field_name = namer_.Field(field);
+ code += " private " + type_name + " " + field_name + ";\n";
+ }
+ // Generate Java getters and setters
+ code += "\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const 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;
+ const auto field_name = namer_.Field(field);
+ const auto get_field = namer_.Method("get", field);
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, false, true);
+ if (field.IsScalarOptional())
+ type_name = ConvertPrimitiveTypeToObjectWrapper_ObjectAPI(type_name);
+
+ code += " public " + type_name + " " + get_field + "() { return " +
+ field_name + "; }\n\n";
+ std::string array_validation = "";
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ array_validation =
+ "if (" + field_name + " != null && " + field_name +
+ ".length == " + NumToString(field.value.type.fixed_length) + ") ";
+ }
+ code += " public void " + namer_.Method("set", field) + "(" + type_name +
+ " " + field_name + ") { " + array_validation + "this." +
+ field_name + " = " + field_name + "; }\n\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) {
+ const 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;
+ const auto get_field = namer_.Method("get", field);
+
+ code += " this." + namer_.Field(field) + " = ";
+ const auto type_name =
+ GenTypeGet_ObjectAPI(field.value.type, false, true);
+ if (IsScalar(field.value.type.base_type)) {
+ if (field.IsScalarOptional()) {
+ code += "null;\n";
+ } else {
+ 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";
+ if (parser_.root_struct_def_ == &struct_def) {
+ const std::string struct_type = namer_.Type(struct_def);
+ code += " public static " + class_name +
+ " deserializeFromBinary(byte[] fbBuffer) {\n";
+ code += " return " + struct_type + "." +
+ namer_.LegacyJavaMethod2("getRootAs", struct_def, "") +
+ "(ByteBuffer.wrap(fbBuffer)).unpack();\n";
+ code += " }\n";
+ code += " public byte[] serializeToBinary() {\n";
+ code += " FlatBufferBuilder fbb = new FlatBufferBuilder();\n";
+ code += " " + struct_type + "." +
+ namer_.LegacyJavaMethod2("finish", struct_def, "Buffer") +
+ "(fbb, " + struct_type + ".pack(fbb, this));\n";
+ code += " return fbb.sizedByteArray();\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_;
+ const IdlNamer namer_;
+
+ private:
+ std::string Prefixed(const std::string &str) const {
+ return package_prefix_ + str;
+ }
+
+ std::string package_prefix_;
+ Namespace package_prefix_ns_;
+
};
} // namespace java
bool GenerateJava(const Parser &parser, const std::string &path,
const std::string &file_name) {
- java::JavaGenerator generator(parser, path, file_name);
+ java::JavaGenerator generator(parser, path, file_name,
+ parser.opts.java_package_prefix);
return generator.generate();
}
+namespace {
+
+class JavaCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateJava(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = JavaMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateJavaGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kJava; }
+
+ std::string LanguageName() const override { return "Java"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewJavaCodeGenerator() {
+ return std::unique_ptr<JavaCodeGenerator>(new JavaCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_java.h b/contrib/libs/flatbuffers/src/idl_gen_java.h
new file mode 100644
index 0000000000..20798a4484
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_java.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_JAVA_H_
+#define FLATBUFFERS_IDL_GEN_JAVA_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Java code generator.
+std::unique_ptr<CodeGenerator> NewJavaCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_JAVA_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp b/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
index d58bb84976..3849da856a 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#include "idl_gen_json_schema.h"
+
+#include <algorithm>
#include <iostream>
+#include <limits>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/idl.h"
@@ -24,7 +28,10 @@ namespace flatbuffers {
namespace jsons {
-template<class T> std::string GenFullName(const T *enum_def) {
+namespace {
+
+template<class T>
+static 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) {
@@ -34,15 +41,16 @@ template<class T> std::string GenFullName(const T *enum_def) {
return full_name;
}
-template<class T> std::string GenTypeRef(const T *enum_def) {
+template<class T>
+static std::string GenTypeRef(const T *enum_def) {
return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
}
-std::string GenType(const std::string &name) {
+static std::string GenType(const std::string &name) {
return "\"type\" : \"" + name + "\"";
}
-std::string GenType(BaseType type) {
+static std::string GenType(BaseType type) {
switch (type) {
case BASE_TYPE_BOOL: return "\"type\" : \"boolean\"";
case BASE_TYPE_CHAR:
@@ -84,13 +92,13 @@ std::string GenType(BaseType type) {
}
}
-std::string GenBaseType(const Type &type) {
+static 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) {
+static std::string GenArrayType(const Type &type) {
std::string element_type;
if (type.struct_def != nullptr) {
element_type = GenTypeRef(type.struct_def);
@@ -103,7 +111,7 @@ std::string GenArrayType(const Type &type) {
return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
}
-std::string GenType(const Type &type) {
+static std::string GenType(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
@@ -136,6 +144,8 @@ std::string GenType(const Type &type) {
}
}
+} // namespace
+
class JsonSchemaGenerator : public BaseGenerator {
private:
std::string code_;
@@ -166,9 +176,45 @@ class JsonSchemaGenerator : public BaseGenerator {
return std::string(num_spaces, ' ');
}
+ std::string PrepareDescription(
+ const std::vector<std::string> &comment_lines) {
+ std::string comment;
+ for (auto line_iterator = comment_lines.cbegin();
+ line_iterator != comment_lines.cend(); ++line_iterator) {
+ const auto &comment_line = *line_iterator;
+
+ // remove leading and trailing spaces from comment line
+ const auto start = std::find_if(comment_line.begin(), comment_line.end(),
+ [](char c) { return !isspace(c); });
+ const auto end =
+ std::find_if(comment_line.rbegin(), comment_line.rend(), [](char c) {
+ return !isspace(c);
+ }).base();
+ if (start < end) {
+ comment.append(start, end);
+ } else {
+ comment.append(comment_line);
+ }
+
+ if (line_iterator + 1 != comment_lines.cend()) comment.append("\n");
+ }
+ if (!comment.empty()) {
+ std::string description;
+ if (EscapeString(comment.c_str(), comment.length(), &description, true,
+ true)) {
+ return description;
+ }
+ return "";
+ }
+ return "";
+ }
+
bool generate() {
code_ = "";
- if (parser_.root_struct_def_ == nullptr) { return false; }
+ if (parser_.root_struct_def_ == nullptr) {
+ std::cerr << "Error: Binary schema not generated, no root struct found\n";
+ return false;
+ }
code_ += "{" + NewLine();
code_ += Indent(1) +
"\"$schema\": \"https://json-schema.org/draft/2019-09/schema\"," +
@@ -193,21 +239,12 @@ class JsonSchemaGenerator : public BaseGenerator {
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();
+ auto comment = PrepareDescription(comment_lines);
+ if (comment != "") {
+ code_ += Indent(3) + "\"description\" : " + comment + "," + NewLine();
}
+
code_ += Indent(3) + "\"properties\" : {" + NewLine();
const auto &properties = structure->fields.vec;
@@ -223,13 +260,19 @@ class JsonSchemaGenerator : public BaseGenerator {
std::string deprecated_info = "";
if (property->deprecated) {
deprecated_info =
- "," + NewLine() + Indent(8) + "\"deprecated\" : true,";
+ "," + 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;
+ auto description = PrepareDescription(property->doc_comment);
+ if (description != "") {
+ typeLine +=
+ "," + NewLine() + Indent(8) + "\"description\" : " + description;
+ }
+
typeLine += NewLine() + Indent(7) + "}";
if (property != properties.back()) { typeLine.append(","); }
code_ += typeLine + NewLine();
@@ -289,4 +332,63 @@ bool GenerateJsonSchema(const Parser &parser, std::string *json) {
*json = generator.getJson();
return true;
}
+
+namespace {
+
+class JsonSchemaCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateJsonSchema(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override {
+ return IDLOptions::kJsonSchema;
+ }
+
+ std::string LanguageName() const override { return "JsonSchema"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewJsonSchemaCodeGenerator() {
+ return std::unique_ptr<JsonSchemaCodeGenerator>(
+ new JsonSchemaCodeGenerator());
+}
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_json_schema.h b/contrib/libs/flatbuffers/src/idl_gen_json_schema.h
new file mode 100644
index 0000000000..37a7a09569
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_json_schema.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 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_GEN_JSON_SCHEMA_H_
+#define FLATBUFFERS_IDL_GEN_JSON_SCHEMA_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new JsonSchema Code generator.
+std::unique_ptr<CodeGenerator> NewJsonSchemaCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_JSON_SCHEMA_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
index fb4ce87a67..eeaca94854 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_kotlin.h"
+
#include <functional>
#include <unordered_set>
@@ -23,14 +25,14 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
-#if defined(FLATBUFFERS_CPP98_STL)
-# include <cctype>
-#endif // defined(FLATBUFFERS_CPP98_STL)
+#include "idl_namer.h"
namespace flatbuffers {
namespace kotlin {
+namespace {
+
typedef std::map<std::string, std::pair<std::string, std::string> > FbbParamMap;
static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
"POSITIVE_INFINITY",
@@ -38,40 +40,54 @@ static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN",
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); }
- }
+static std::set<std::string> KotlinKeywords() {
+ return { "package", "as", "typealias", "class", "this", "super",
+ "val", "var", "fun", "for", "null", "true",
+ "false", "is", "in", "throw", "return", "break",
+ "continue", "object", "if", "try", "else", "while",
+ "do", "when", "interface", "typeof", "Any", "Character" };
+}
- return MakeCamel(name, false);
+static Namer::Config KotlinDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kKeep,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kKeep,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"", // I.e. Concatenate.
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"__",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".kt" };
}
+} // namespace
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) {}
+ namer_(WithFlagOptions(KotlinDefaultConfig(), parser.opts, path),
+ KotlinKeywords()) {}
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();
@@ -86,8 +102,6 @@ class KotlinGenerator : public BaseGenerator {
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();
@@ -120,19 +134,31 @@ class KotlinGenerator : public BaseGenerator {
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 +=
+ "import com.google.flatbuffers.BaseVector\n"
+ "import com.google.flatbuffers.BooleanVector\n"
+ "import com.google.flatbuffers.ByteVector\n"
+ "import com.google.flatbuffers.Constants\n"
+ "import com.google.flatbuffers.DoubleVector\n"
+ "import com.google.flatbuffers.FlatBufferBuilder\n"
+ "import com.google.flatbuffers.FloatVector\n"
+ "import com.google.flatbuffers.LongVector\n"
+ "import com.google.flatbuffers.StringVector\n"
+ "import com.google.flatbuffers.Struct\n"
+ "import com.google.flatbuffers.Table\n"
+ "import com.google.flatbuffers.UnionVector\n"
+ "import java.nio.ByteBuffer\n"
+ "import java.nio.ByteOrder\n"
+ "import kotlin.math.sign\n\n";
}
code += classcode;
- auto filename = NamespaceDir(ns) + defname + ".kt";
+ const std::string dirs = namer_.Directories(ns);
+ EnsureDirExists(dirs);
+ const std::string filename =
+ dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix);
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);
}
@@ -167,10 +193,11 @@ class KotlinGenerator : public BaseGenerator {
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) ||
+ (!field.IsRequired() &&
+ (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 &&
+ (base_type == BASE_TYPE_VECTOR && !field.IsRequired() &&
!IsScalar(field.value.type.VectorType().base_type))) {
r_type += "?";
}
@@ -262,8 +289,7 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(enum_def.doc_comment, writer, &comment_config);
writer += "@Suppress(\"unused\")";
- writer += "@ExperimentalUnsignedTypes";
- writer += "class " + Esc(enum_def.name) + " private constructor() {";
+ writer += "class " + namer_.Type(enum_def) + " private constructor() {";
writer.IncrementIdentLevel();
GenerateCompanionObject(writer, [&]() {
@@ -274,7 +300,7 @@ class KotlinGenerator : public BaseGenerator {
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("name", namer_.Variant(ev.name));
writer.SetValue("type", field_type);
writer.SetValue("val", val + suffix);
GenerateComment(ev.doc_comment, writer, &comment_config);
@@ -289,7 +315,10 @@ class KotlinGenerator : public BaseGenerator {
// 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) {
+ bool generate_names =
+ range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness &&
+ parser_.opts.mini_reflect == IDLOptions::kTypesAndNames;
+ if (generate_names) {
GeneratePropertyOneLine(writer, "names", "Array<String>", [&]() {
writer += "arrayOf(\\";
auto val = enum_def.Vals().front();
@@ -341,7 +370,8 @@ class KotlinGenerator : public BaseGenerator {
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));
+ return bb_var_name + "." +
+ namer_.Method("get", GenTypeBasic(type.base_type));
}
}
@@ -361,7 +391,8 @@ class KotlinGenerator : public BaseGenerator {
case BASE_TYPE_BOOL:
case BASE_TYPE_NONE:
case BASE_TYPE_UTYPE: return "bb.put";
- default: return "bb.put" + MakeCamel(GenTypeBasic(type.base_type));
+ default:
+ return "bb." + namer_.Method("put", GenTypeBasic(type.base_type));
}
}
return "";
@@ -384,8 +415,8 @@ class KotlinGenerator : public BaseGenerator {
// Recursively generate arguments for a constructor, to deal with nested
// structs.
- static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
- const char *nameprefix) {
+ void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) const {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
@@ -398,7 +429,7 @@ class KotlinGenerator : public BaseGenerator {
(nameprefix + (field.name + "_")).c_str());
} else {
writer += std::string(", ") + nameprefix + "\\";
- writer += MakeCamel(field.name) + ": \\";
+ writer += namer_.Field(field) + ": \\";
writer += GenTypeBasic(field.value.type.base_type) + "\\";
}
}
@@ -407,8 +438,8 @@ class KotlinGenerator : public BaseGenerator {
// 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) {
+ void GenStructBody(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) const {
writer.SetValue("align", NumToString(struct_def.minalign));
writer.SetValue("size", NumToString(struct_def.bytesize));
writer += "builder.prep({{align}}, {{size}})";
@@ -425,7 +456,7 @@ class KotlinGenerator : public BaseGenerator {
(nameprefix + (field.name + "_")).c_str());
} else {
writer.SetValue("type", GenMethod(field.value.type));
- writer.SetValue("argname", nameprefix + MakeCamel(field.name, false));
+ writer.SetValue("argname", nameprefix + namer_.Variable(field));
writer.SetValue("cast", CastToSigned(field.value.type));
writer += "builder.put{{type}}({{argname}}{{cast}})";
}
@@ -459,11 +490,10 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(struct_def.doc_comment, writer, &comment_config);
auto fixed = struct_def.fixed;
- writer.SetValue("struct_name", Esc(struct_def.name));
+ writer.SetValue("struct_name", namer_.Type(struct_def));
writer.SetValue("superclass", fixed ? "Struct" : "Table");
writer += "@Suppress(\"unused\")";
- writer += "@ExperimentalUnsignedTypes";
writer += "class {{struct_name}} : {{superclass}}() {\n";
writer.IncrementIdentLevel();
@@ -476,7 +506,7 @@ class KotlinGenerator : public BaseGenerator {
// Generate assign method
GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
- Esc(struct_def.name), [&]() {
+ namer_.Type(struct_def), [&]() {
writer += "__init(_i, _bb)";
writer += "return this";
});
@@ -489,15 +519,15 @@ class KotlinGenerator : public BaseGenerator {
if (!struct_def.fixed) {
FieldDef *key_field = nullptr;
- // Generate verson check method.
+ // Generate version check method.
// Force compile time error if not using the same version
// runtime.
GenerateFunOneLine(
writer, "validateVersion", "", "",
- [&]() { writer += "Constants.FLATBUFFERS_2_0_0()"; },
+ [&]() { writer += "Constants.FLATBUFFERS_23_5_9()"; },
options.gen_jvmstatic);
- GenerateGetRootAsAccessors(Esc(struct_def.name), writer, options);
+ GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
GenerateBufferHasIdentifier(struct_def, writer, options);
GenerateTableCreator(struct_def, writer, options);
@@ -549,7 +579,7 @@ class KotlinGenerator : public BaseGenerator {
void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def,
CodeWriter &writer, const IDLOptions options) const {
std::stringstream params;
- params << "obj: " << Esc(struct_def.name) << "?"
+ params << "obj: " << namer_.Type(struct_def) << "?"
<< ", ";
params << "vectorLocation: Int, ";
params << "key: " << GenTypeGet(key_field->value.type) << ", ";
@@ -557,7 +587,7 @@ class KotlinGenerator : public BaseGenerator {
auto statements = [&]() {
auto base_type = key_field->value.type.base_type;
- writer.SetValue("struct_name", Esc(struct_def.name));
+ writer.SetValue("struct_name", namer_.Type(struct_def));
if (base_type == BASE_TYPE_STRING) {
writer +=
"val byteKey = key."
@@ -603,7 +633,8 @@ class KotlinGenerator : public BaseGenerator {
writer += "return null";
};
GenerateFun(writer, "__lookup_by_key", params.str(),
- Esc(struct_def.name) + "?", statements, options.gen_jvmstatic);
+ namer_.Type(struct_def) + "?", statements,
+ options.gen_jvmstatic);
}
void GenerateFinishSizePrefixed(StructDef &struct_def,
@@ -612,7 +643,8 @@ class KotlinGenerator : public BaseGenerator {
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";
+ auto method_name =
+ namer_.LegacyJavaMethod2("finishSizePrefixed", struct_def, "Buffer");
GenerateFunOneLine(
writer, method_name, params, "",
[&]() { writer += "builder.finishSizePrefixed(offset" + id + ")"; },
@@ -624,7 +656,8 @@ class KotlinGenerator : public BaseGenerator {
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";
+ auto method_name =
+ namer_.LegacyKotlinMethod("finish", struct_def, "Buffer");
GenerateFunOneLine(
writer, method_name, params, "",
[&]() { writer += "builder.finish(offset" + id + ")"; },
@@ -634,7 +667,7 @@ class KotlinGenerator : public BaseGenerator {
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 name = namer_.LegacyJavaMethod2("end", struct_def, "");
auto params = "builder: FlatBufferBuilder";
auto returns = "Int";
auto field_vec = struct_def.fields.vec;
@@ -660,7 +693,7 @@ class KotlinGenerator : public BaseGenerator {
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 method_name = namer_.Method("create", field, "vector");
auto params = "builder: FlatBufferBuilder, data: " +
GenTypeBasic(vector_type.base_type) + "Array";
writer.SetValue("size", NumToString(InlineSize(vector_type)));
@@ -668,6 +701,9 @@ class KotlinGenerator : public BaseGenerator {
writer.SetValue("root", GenMethod(vector_type));
writer.SetValue("cast", CastToSigned(vector_type));
+ if (IsUnsigned(vector_type.base_type)) {
+ writer += "@kotlin.ExperimentalUnsignedTypes";
+ }
GenerateFun(
writer, method_name, params, "Int",
[&]() {
@@ -692,8 +728,7 @@ class KotlinGenerator : public BaseGenerator {
writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
GenerateFunOneLine(
- writer, "start" + MakeCamel(Esc(field.name) + "Vector", true), params,
- "",
+ writer, namer_.Method("start", field, "Vector"), params, "",
[&]() {
writer += "builder.startVector({{size}}, numElems, {{align}})";
},
@@ -703,23 +738,36 @@ class KotlinGenerator : public BaseGenerator {
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);
+ auto secondArg = namer_.Variable(field.name) + ": " + field_type;
+
+ auto content = [&]() {
+ auto method = GenMethod(field.value.type);
+ writer.SetValue("field_name", namer_.Field(field));
+ writer.SetValue("method_name", method);
+ writer.SetValue("pos", field_pos);
+ writer.SetValue("default", GenFBBDefaultValue(field));
+ writer.SetValue("cast", GenFBBValueCast(field));
+ if (field.key) {
+ // field has key attribute, so always need to exist
+ // even if its value is equal to default.
+ // Generated code will bypass default checking
+ // resulting in { builder.addShort(name); slot(id); }
+ writer += "builder.add{{method_name}}({{field_name}}{{cast}})";
+ writer += "builder.slot({{pos}})";
+ } else {
+ writer += "builder.add{{method_name}}({{pos}}, \\";
+ writer += "{{field_name}}{{cast}}, {{default}})";
+ }
+ };
+ auto signature = namer_.LegacyKotlinMethod("add", field, "");
+ auto params = "builder: FlatBufferBuilder, " + secondArg;
+ if (field.key) {
+ GenerateFun(writer, signature, params, "", content,
+ options.gen_jvmstatic);
+ } else {
+ GenerateFunOneLine(writer, signature, params, "", content,
+ options.gen_jvmstatic);
+ }
}
static std::string ToSignedType(const Type &type) {
@@ -763,7 +811,8 @@ class KotlinGenerator : public BaseGenerator {
void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code,
const IDLOptions options) const {
GenerateFunOneLine(
- code, "start" + Esc(struct_def.name), "builder: FlatBufferBuilder", "",
+ code, namer_.LegacyJavaMethod2("start", struct_def, ""),
+ "builder: FlatBufferBuilder", "",
[&]() {
code += "builder.startTable(" +
NumToString(struct_def.fields.vec.size()) + ")";
@@ -795,13 +844,13 @@ class KotlinGenerator : public BaseGenerator {
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
- auto name = "create" + Esc(struct_def.name);
+ auto name = namer_.LegacyJavaMethod2("create", struct_def, "");
std::stringstream params;
params << "builder: FlatBufferBuilder";
for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- params << ", " << MakeCamel(Esc(field.name), false);
+ params << ", " << namer_.Variable(field);
if (!IsScalar(field.value.type.base_type)) {
params << "Offset: ";
} else {
@@ -827,17 +876,15 @@ class KotlinGenerator : public BaseGenerator {
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));
+ writer.SetValue("field_name", namer_.Field(field));
// we wrap on null check for scalar optionals
writer += field.IsScalarOptional()
? "{{field_name}}?.run { \\"
: "\\";
- writer += "add{{camel_field_name}}(builder, {{field_name}}\\";
+ writer += namer_.LegacyKotlinMethod("add", field, "") +
+ "(builder, {{field_name}}\\";
if (!IsScalar(field.value.type.base_type)) {
writer += "Offset\\";
}
@@ -857,7 +904,7 @@ class KotlinGenerator : public BaseGenerator {
// 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);
+ auto name = namer_.Function(struct_def);
GenerateFunOneLine(
writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", "Boolean",
[&]() {
@@ -876,7 +923,7 @@ class KotlinGenerator : public BaseGenerator {
GenerateComment(field.doc_comment, writer, &comment_config);
- auto field_name = MakeCamel(Esc(field.name), false);
+ auto field_name = namer_.Field(field);
auto field_type = GenTypeGet(field.value.type);
auto field_default_value = GenDefaultValue(field);
auto return_type = GetterReturnType(field);
@@ -960,7 +1007,15 @@ class KotlinGenerator : public BaseGenerator {
OffsetWrapper(
writer, offset_val,
[&]() { writer += "obj.__assign({{seek}}, bb)"; },
- [&]() { writer += "null"; });
+ [&]() {
+ if (field.IsRequired()) {
+ writer +=
+ "throw AssertionError(\"No value for "
+ "(required) field {{field_name}}\")";
+ } else {
+ writer += "null";
+ }
+ });
});
}
break;
@@ -970,12 +1025,30 @@ class KotlinGenerator : public BaseGenerator {
// val Name : String?
// get() = {
// val o = __offset(10)
- // return if (o != 0) __string(o + bb_pos) else null
+ // 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";
+ writer += "return if (o != 0) {";
+ writer.IncrementIdentLevel();
+ writer += "__string(o + bb_pos)";
+ writer.DecrementIdentLevel();
+ writer += "} else {";
+ writer.IncrementIdentLevel();
+ if (field.IsRequired()) {
+ writer +=
+ "throw AssertionError(\"No value for (required) field "
+ "{{field_name}}\")";
+ } else {
+ writer += "null";
+ }
+ writer.DecrementIdentLevel();
+ writer += "}";
});
break;
case BASE_TYPE_VECTOR: {
@@ -1000,7 +1073,11 @@ class KotlinGenerator : public BaseGenerator {
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 not_found =
+ field.IsRequired()
+ ? "throw IndexOutOfBoundsException(\"Index out of range: "
+ "$j, vector {{field_name}} is empty\")"
+ : NotFoundReturn(field.value.type.element);
auto found = "";
writer.SetValue("index", index);
switch (vectortype.base_type) {
@@ -1047,7 +1124,7 @@ class KotlinGenerator : public BaseGenerator {
auto &kfield = **kit;
if (kfield.key) {
auto qualified_name = WrapInNameSpace(sd);
- auto name = MakeCamel(Esc(field.name), false) + "ByKey";
+ auto name = namer_.Method(field, "ByKey");
auto params = "key: " + GenTypeGet(kfield.value.type);
auto rtype = qualified_name + "?";
GenerateFun(writer, name, params, rtype, [&]() {
@@ -1140,9 +1217,9 @@ class KotlinGenerator : public BaseGenerator {
auto underlying_type = value_base_type == BASE_TYPE_VECTOR
? value_type.VectorType()
: value_type;
- auto name = "mutate" + MakeCamel(Esc(field.name), true);
+ auto name = namer_.LegacyKotlinMethod("mutate", field, "");
auto size = NumToString(InlineSize(underlying_type));
- auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type);
+ auto params = namer_.Field(field) + ": " + 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, ");
@@ -1151,8 +1228,8 @@ class KotlinGenerator : public BaseGenerator {
// representation.
auto setter_parameter =
underlying_type.base_type == BASE_TYPE_BOOL
- ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()"
- : Esc(field.name);
+ ? "(if(" + namer_.Field(field) + ") 1 else 0).toByte()"
+ : namer_.Field(field);
auto setter_index =
value_base_type == BASE_TYPE_VECTOR
@@ -1285,9 +1362,9 @@ class KotlinGenerator : public BaseGenerator {
}
}
- static void GenerateGetRootAsAccessors(const std::string &struct_name,
- CodeWriter &writer,
- IDLOptions options) {
+ void GenerateGetRootAsAccessors(const std::string &struct_name,
+ CodeWriter &writer,
+ IDLOptions options) const {
// Generate a special accessor for the table that when used as the root
// ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...}
writer.SetValue("gr_name", struct_name);
@@ -1313,13 +1390,12 @@ class KotlinGenerator : public BaseGenerator {
writer += "}";
}
- static void GenerateStaticConstructor(const StructDef &struct_def,
- CodeWriter &code,
- const IDLOptions options) {
+ void GenerateStaticConstructor(const StructDef &struct_def, CodeWriter &code,
+ const IDLOptions options) const {
// create a struct constructor function
auto params = StructConstructorParams(struct_def);
GenerateFun(
- code, "create" + Esc(struct_def.name), params, "Int",
+ code, namer_.LegacyJavaMethod2("create", struct_def, ""), params, "Int",
[&]() {
GenStructBody(struct_def, code, "");
code += "return builder.offset()";
@@ -1327,8 +1403,8 @@ class KotlinGenerator : public BaseGenerator {
options.gen_jvmstatic);
}
- static std::string StructConstructorParams(const StructDef &struct_def,
- const std::string &prefix = "") {
+ std::string StructConstructorParams(const StructDef &struct_def,
+ const std::string &prefix = "") const {
// builder: FlatBufferBuilder
std::stringstream out;
auto field_vec = struct_def.fields.vec;
@@ -1341,9 +1417,9 @@ class KotlinGenerator : public BaseGenerator {
// constructing a nested struct, prefix the name with the field
// name.
out << StructConstructorParams(*field.value.type.struct_def,
- prefix + (Esc(field.name) + "_"));
+ prefix + (namer_.Variable(field) + "_"));
} else {
- out << ", " << prefix << MakeCamel(Esc(field.name), false) << ": "
+ out << ", " << prefix << namer_.Variable(field) << ": "
<< GenTypeBasic(field.value.type.base_type);
}
}
@@ -1513,9 +1589,7 @@ class KotlinGenerator : public BaseGenerator {
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_;
+ const IdlNamer namer_;
};
} // namespace kotlin
@@ -1524,4 +1598,61 @@ bool GenerateKotlin(const Parser &parser, const std::string &path,
kotlin::KotlinGenerator generator(parser, path, file_name);
return generator.generate();
}
+
+namespace {
+
+class KotlinCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateKotlin(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kKotlin; }
+
+ std::string LanguageName() const override { return "Kotlin"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewKotlinCodeGenerator() {
+ return std::unique_ptr<KotlinCodeGenerator>(new KotlinCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin.h b/contrib/libs/flatbuffers/src/idl_gen_kotlin.h
new file mode 100644
index 0000000000..22d8ff6ca3
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_KOTLIN_H_
+#define FLATBUFFERS_IDL_GEN_KOTLIN_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Kotlin code generator.
+std::unique_ptr<CodeGenerator> NewKotlinCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_KOTLIN_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
index 6fdd6dc26a..a8b0a6f7a5 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idl_gen_lobster.h"
+
#include <string>
#include <unordered_set>
@@ -60,7 +62,10 @@ class LobsterGenerator : public BaseGenerator {
std::string GenTypeName(const Type &type) {
auto bits = NumToString(SizeOf(type.base_type) * 8);
- if (IsInteger(type.base_type)) return "int" + bits;
+ if (IsInteger(type.base_type)) {
+ if (IsUnsigned(type.base_type)) return "uint" + bits;
+ else 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";
@@ -69,16 +74,18 @@ class LobsterGenerator : public BaseGenerator {
std::string LobsterType(const Type &type) {
if (IsFloat(type.base_type)) return "float";
+ if (IsBool(type.base_type)) return "bool";
if (IsScalar(type.base_type) && type.enum_def)
return NormalizedName(*type.enum_def);
if (!IsScalar(type.base_type)) return "flatbuffers_offset";
+ if (IsString(type)) return "string";
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))
+ ? ConvertCase(GenTypeBasic(type), Case::kUpperCamel)
: (IsStruct(type) ? "Struct" : "UOffsetTRelative");
}
@@ -113,21 +120,27 @@ class LobsterGenerator : public BaseGenerator {
auto defval = field.IsOptional() ? "0" : field.value.constant;
acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) +
"(pos_, " + offsets + ", " + defval + ")";
+ if (IsBool(field.value.type.base_type))
+ acc = "bool(" + acc + ")";
}
if (field.value.type.enum_def)
acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")";
- if (field.IsOptional())
+ if (field.IsOptional()) {
acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")";
- code += def + "():\n return " + acc + "\n";
+ code += def + "() -> " + LobsterType(field.value.type) + ", bool:\n return " + acc + "\n";
+ } else {
+ code += def + "() -> " + LobsterType(field.value.type) + ":\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 += def + "() -> " + name + ":\n ";
code += "return " + name + "{ buf_, pos_ + " + offsets + " }\n";
} else {
+ code += def + "() -> " + name + "?:\n ";
code += std::string("let o = buf_.flatbuffers_field_") +
(field.value.type.struct_def->fixed ? "struct" : "table") +
"(pos_, " + offsets + ")\n return if o: " + name +
@@ -137,25 +150,28 @@ class LobsterGenerator : public BaseGenerator {
}
case BASE_TYPE_STRING:
code += def +
- "():\n return buf_.flatbuffers_field_string(pos_, " +
+ "() -> string:\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 += def + "(i:int) -> " + NamespacedName(*field.value.type.struct_def) + ":\n return ";
code += NamespacedName(*field.value.type.struct_def) + " { buf_, " +
start + " }\n";
} else {
- if (IsString(vectortype))
+ if (IsString(vectortype)) {
+ code += def + "(i:int) -> string:\n return ";
code += "buf_.flatbuffers_string";
- else
+ } else {
+ code += def + "(i:int) -> " + LobsterType(vectortype) + ":\n return ";
code += "buf_.read_" + GenTypeName(vectortype) + "_le";
+ }
code += "(buf_.flatbuffers_field_vector(pos_, " + offsets +
") + i * " + NumToString(InlineSize(vectortype)) + ")\n";
}
@@ -178,7 +194,7 @@ class LobsterGenerator : public BaseGenerator {
}
if (IsVector(field.value.type)) {
code += def +
- "_length():\n return "
+ "_length() -> int:\n return "
"buf_.flatbuffers_field_vector_len(pos_, " +
offsets + ")\n";
}
@@ -212,7 +228,7 @@ class LobsterGenerator : public BaseGenerator {
if (field.deprecated) continue;
if (IsVector(field.value.type)) {
code += "def " + NormalizedName(struct_def) + "Start" +
- MakeCamel(NormalizedName(field)) +
+ ConvertCase(NormalizedName(field), Case::kUpperCamel) +
"Vector(b_:flatbuffers_builder, n_:int):\n b_.StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
@@ -222,7 +238,7 @@ class LobsterGenerator : public BaseGenerator {
if (vector_type.base_type != BASE_TYPE_STRUCT ||
!vector_type.struct_def->fixed) {
code += "def " + NormalizedName(struct_def) + "Create" +
- MakeCamel(NormalizedName(field)) +
+ ConvertCase(NormalizedName(field), Case::kUpperCamel) +
"Vector(b_:flatbuffers_builder, v_:[" +
LobsterType(vector_type) + "]):\n b_.StartVector(" +
NumToString(elem_size) + ", v_.length, " +
@@ -388,4 +404,63 @@ bool GenerateLobster(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace {
+
+class LobsterCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateLobster(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override {
+ return IDLOptions::kLobster;
+ }
+
+ std::string LanguageName() const override { return "Lobster"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewLobsterCodeGenerator() {
+ return std::unique_ptr<LobsterCodeGenerator>(new LobsterCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lobster.h b/contrib/libs/flatbuffers/src/idl_gen_lobster.h
new file mode 100644
index 0000000000..284303edce
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_lobster.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_LOBSTER_H_
+#define FLATBUFFERS_IDL_GEN_LOBSTER_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Lobster code generator.
+std::unique_ptr<CodeGenerator> NewLobsterCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_LOBSTER_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lua.cpp b/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
index 9efc435e24..551a4b26f8 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_lua.h"
+
#include <string>
#include <unordered_set>
@@ -154,7 +156,8 @@ class LuaGenerator : public BaseGenerator {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field)) + "Length()\n";
+ code +=
+ ConvertCase(NormalizedName(field), Case::kUpperCamel) + "Length()\n";
code += OffsetPrefix(field);
code +=
std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
@@ -169,7 +172,7 @@ class LuaGenerator : public BaseGenerator {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += std::string(Indent) + "return " + getter;
code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) +
@@ -183,7 +186,7 @@ class LuaGenerator : public BaseGenerator {
std::string &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
getter += std::string("o + ") + SelfDataPos + ")";
@@ -207,7 +210,7 @@ class LuaGenerator : public BaseGenerator {
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(obj)\n";
code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " +
SelfDataPos + " + ";
@@ -222,7 +225,7 @@ class LuaGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
if (field.value.type.struct_def->fixed) {
@@ -246,7 +249,7 @@ class LuaGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "()\n";
code += OffsetPrefix(field);
code +=
@@ -261,7 +264,7 @@ class LuaGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field)) + "()\n";
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel) + "()\n";
code += OffsetPrefix(field);
// TODO(rw): this works and is not the good way to it:
@@ -292,7 +295,7 @@ class LuaGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(j)\n";
code += OffsetPrefix(field);
code +=
@@ -321,7 +324,7 @@ class LuaGenerator : public BaseGenerator {
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(j)\n";
code += OffsetPrefix(field);
code +=
@@ -344,7 +347,7 @@ class LuaGenerator : public BaseGenerator {
const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "AsString(start, stop)\n";
code += std::string(Indent) + "return " + SelfData + ":VectorAsString(" +
NumToString(field.value.offset) + ", start, stop)\n";
@@ -377,7 +380,7 @@ class LuaGenerator : public BaseGenerator {
} else {
std::string &code = *code_ptr;
code += std::string(", ") + nameprefix;
- code += MakeCamel(NormalizedName(field), false);
+ code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
}
}
}
@@ -409,7 +412,8 @@ class LuaGenerator : public BaseGenerator {
} else {
code +=
std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
- code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
+ code += nameprefix +
+ ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")\n";
}
}
}
@@ -435,9 +439,9 @@ class LuaGenerator : public BaseGenerator {
const size_t offset, std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Add" +
- MakeCamel(NormalizedName(field));
+ ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "(builder, ";
- code += MakeCamel(NormalizedName(field), false);
+ code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
code += ") ";
code += "builder:Prepend";
code += GenMethod(field) + "Slot(";
@@ -446,9 +450,9 @@ class LuaGenerator : public BaseGenerator {
// if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
// code += "flatbuffers.N.UOffsetTFlags.py_type";
// code += "(";
- // code += MakeCamel(NormalizedName(field), false) + ")";
+ // code += ConvertCase(NormalizedName(field), Case::kLowerCamel) + ")";
// } else {
- code += MakeCamel(NormalizedName(field), false);
+ code += ConvertCase(NormalizedName(field), Case::kLowerCamel);
// }
code += ", " + field.value.constant;
code += ") end\n";
@@ -459,7 +463,7 @@ class LuaGenerator : public BaseGenerator {
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "function " + NormalizedName(struct_def) + ".Start";
- code += MakeCamel(NormalizedName(field));
+ code += ConvertCase(NormalizedName(field), Case::kUpperCamel);
code += "Vector(builder, numElems) return builder:StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
@@ -603,14 +607,14 @@ class LuaGenerator : public BaseGenerator {
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default:
return std::string(SelfData) + ":Get(flatbuffers.N." +
- MakeCamel(GenTypeGet(type)) + ", ";
+ ConvertCase(GenTypeGet(type), Case::kUpperCamel) + ", ";
}
}
// 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))
+ ? ConvertCase(GenTypeBasic(field.value.type), Case::kUpperCamel)
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
}
@@ -742,4 +746,61 @@ bool GenerateLua(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace {
+
+class LuaCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateLua(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return true; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kLua; }
+
+ std::string LanguageName() const override { return "Lua"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewLuaCodeGenerator() {
+ return std::unique_ptr<LuaCodeGenerator>(new LuaCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lua.h b/contrib/libs/flatbuffers/src/idl_gen_lua.h
new file mode 100644
index 0000000000..43974a8c33
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_lua.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_LUA_H_
+#define FLATBUFFERS_IDL_GEN_LUA_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Lua code generator.
+std::unique_ptr<CodeGenerator> NewLuaCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_LUA_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_php.cpp b/contrib/libs/flatbuffers/src/idl_gen_php.cpp
index dd3ed68189..a245b1a7c3 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_php.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_php.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_php.h"
+
#include <string>
#include "flatbuffers/code_generators.h"
@@ -181,7 +183,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return int\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name) + "Length()\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "Length()\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $this->__offset(";
code += NumToString(field.value.offset) + ");\n";
@@ -198,7 +200,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return string\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name) + "Bytes()\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "Bytes()\n";
code += Indent + "{\n";
code += Indent + Indent + "return $this->__vector_as_bytes(";
code += NumToString(field.value.offset) + ");\n";
@@ -216,12 +218,12 @@ class PhpGenerator : public BaseGenerator {
code += GenTypeGet(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function " + getter;
- code += MakeCamel(field.name) + "()\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "()\n";
code += Indent + "{\n";
code += Indent + Indent + "return ";
code += "$this->bb->get";
- code += MakeCamel(GenTypeGet(field.value.type));
+ code += ConvertCase(GenTypeGet(field.value.type), Case::kUpperCamel);
code += "($this->bb_pos + ";
code += NumToString(field.value.offset) + ")";
code += ";\n";
@@ -237,14 +239,15 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
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 += ConvertCase(GenTypeGet(field.value.type), Case::kUpperCamel) +
+ "($o + $this->bb_pos)";
code += " : " + GenDefaultValue(field.value) + ";\n";
code += Indent + "}\n\n";
}
@@ -258,7 +261,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name) + "()\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "()\n";
code += Indent + "{\n";
code += Indent + Indent + "$obj = new ";
code += GenTypeGet(field.value.type) + "();\n";
@@ -274,11 +277,12 @@ class PhpGenerator : public BaseGenerator {
std::string &code = *code_ptr;
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "()\n";
code += Indent + "{\n";
code += Indent + Indent + "$obj = new ";
- code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
+ code +=
+ ConvertCase(GenTypeGet(field.value.type), Case::kUpperCamel) + "();\n";
code += Indent + Indent + "$o = $this->__offset(" +
NumToString(field.value.offset) + ");\n";
code += Indent + Indent;
@@ -296,7 +300,7 @@ class PhpGenerator : public BaseGenerator {
void GetStringField(const FieldDef &field, std::string *code_ptr) {
std::string &code = *code_ptr;
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "()\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $this->__offset(" +
@@ -315,7 +319,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name) + "($obj)\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "($obj)\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $this->__offset(" +
NumToString(field.value.offset) + ");\n";
@@ -334,13 +338,14 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
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";
+ code +=
+ ConvertCase(GenTypeGet(field.value.type), Case::kUpperCamel) + "();\n";
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT:
@@ -395,7 +400,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "($j)\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $this->__offset(" +
@@ -408,7 +413,7 @@ class PhpGenerator : public BaseGenerator {
code += GenDefaultValue(field.value) + ";\n";
} else {
code += Indent + Indent + "return $o != 0 ? $this->bb->get";
- code += MakeCamel(GenTypeGet(field.value.type));
+ code += ConvertCase(GenTypeGet(field.value.type), Case::kUpperCamel);
code += "($this->__vector($o) + $j * ";
code += NumToString(InlineSize(vectortype)) + ") : ";
code += GenDefaultValue(field.value) + ";\n";
@@ -427,7 +432,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
code += Indent + " */\n";
code += Indent + "public function get";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "($j, $obj)\n";
code += Indent + "{\n";
code += Indent + Indent + "$o = $this->__offset(" +
@@ -455,7 +460,7 @@ class PhpGenerator : public BaseGenerator {
} else {
std::string &code = *code_ptr;
code += std::string(", $") + nameprefix;
- code += MakeCamel(field.name, false);
+ code += ConvertCase(field.name, Case::kLowerCamel);
}
}
}
@@ -480,7 +485,8 @@ class PhpGenerator : public BaseGenerator {
(nameprefix + (field.name + "_")).c_str(), code_ptr);
} else {
code += Indent + Indent + "$builder->put" + GenMethod(field) + "($";
- code += nameprefix + MakeCamel(field.name, false) + ");\n";
+ code +=
+ nameprefix + ConvertCase(field.name, Case::kLowerCamel) + ");\n";
}
}
}
@@ -528,7 +534,8 @@ class PhpGenerator : public BaseGenerator {
if (field.deprecated) continue;
code += Indent + Indent + "self::add";
- code += MakeCamel(field.name) + "($builder, $" + field.name + ");\n";
+ code += ConvertCase(field.name, Case::kUpperCamel) + "($builder, $" +
+ field.name + ");\n";
}
code += Indent + Indent + "$o = $builder->endObject();\n";
@@ -557,16 +564,16 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return void\n";
code += Indent + " */\n";
code += Indent + "public static function ";
- code += "add" + MakeCamel(field.name);
+ code += "add" + ConvertCase(field.name, Case::kUpperCamel);
code += "(FlatBufferBuilder $builder, ";
- code += "$" + MakeCamel(field.name, false);
+ code += "$" + ConvertCase(field.name, Case::kLowerCamel);
code += ")\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->add";
code += GenMethod(field) + "X(";
code += NumToString(offset) + ", ";
- code += "$" + MakeCamel(field.name, false);
+ code += "$" + ConvertCase(field.name, Case::kLowerCamel);
code += ", ";
if (field.value.type.base_type == BASE_TYPE_BOOL) {
@@ -591,7 +598,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return int vector offset\n";
code += Indent + " */\n";
code += Indent + "public static function create";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "Vector(FlatBufferBuilder $builder, array $data)\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->startVector(";
@@ -603,7 +610,8 @@ class PhpGenerator : public BaseGenerator {
if (IsScalar(field.value.type.VectorType().base_type)) {
code += Indent + Indent + Indent;
code += "$builder->put";
- code += MakeCamel(GenTypeBasic(field.value.type.VectorType()));
+ code += ConvertCase(GenTypeBasic(field.value.type.VectorType()),
+ Case::kUpperCamel);
code += "($data[$i]);\n";
} else {
code += Indent + Indent + Indent;
@@ -619,7 +627,7 @@ class PhpGenerator : public BaseGenerator {
code += Indent + " * @return void\n";
code += Indent + " */\n";
code += Indent + "public static function start";
- code += MakeCamel(field.name);
+ code += ConvertCase(field.name, Case::kUpperCamel);
code += "Vector(FlatBufferBuilder $builder, $numElems)\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->startVector(";
@@ -726,7 +734,7 @@ class PhpGenerator : public BaseGenerator {
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 += ConvertCase(field.name, Case::kUpperCamel);
code += "(FlatBufferBuilder $builder, $offset)\n";
code += Indent + "{\n";
code += Indent + Indent + "$builder->addOffsetX(";
@@ -853,7 +861,7 @@ class PhpGenerator : public BaseGenerator {
// 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))
+ ? ConvertCase(GenTypeBasic(field.value.type), Case::kUpperCamel)
: (IsStruct(field.value.type) ? "Struct" : "Offset");
}
@@ -936,4 +944,62 @@ bool GeneratePhp(const Parser &parser, const std::string &path,
php::PhpGenerator generator(parser, path, file_name);
return generator.generate();
}
+
+namespace {
+
+class PhpCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GeneratePhp(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kPhp; }
+
+ std::string LanguageName() const override { return "Php"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewPhpCodeGenerator() {
+ return std::unique_ptr<PhpCodeGenerator>(new PhpCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_php.h b/contrib/libs/flatbuffers/src/idl_gen_php.h
new file mode 100644
index 0000000000..8695ec9936
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_php.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_PHP_H_
+#define FLATBUFFERS_IDL_GEN_PHP_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Php code generator.
+std::unique_ptr<CodeGenerator> NewPhpCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_PHP_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_python.cpp b/contrib/libs/flatbuffers/src/idl_gen_python.cpp
index b3f394ebf9..dc901bb7c4 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_python.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_python.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_python.h"
+
#include <cctype>
#include <set>
#include <string>
@@ -26,13 +28,53 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace python {
+namespace {
+
+typedef std::pair<std::string, std::string> ImportMapEntry;
+typedef std::set<ImportMapEntry> ImportMap;
+
+static std::set<std::string> PythonKeywords() {
+ return { "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" };
+}
+
+static Namer::Config PythonDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kUpperCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variable=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
+ /*namespaces=*/Case::kKeep, // Packages in python.
+ /*namespace_seperator=*/".",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".py" };
+}
+
// Hardcode spaces per indentation.
-const CommentConfig def_comment = { nullptr, "#", nullptr };
-const std::string Indent = " ";
+static const CommentConfig def_comment = { nullptr, "#", nullptr };
+static const std::string Indent = " ";
+
+} // namespace
class PythonGenerator : public BaseGenerator {
public:
@@ -40,155 +82,147 @@ class PythonGenerator : public BaseGenerator {
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));
- }
+ float_const_gen_("float('nan')", "float('inf')", "float('-inf')"),
+ namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path),
+ PythonKeywords()) {}
// 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) {
+ std::string OffsetPrefix(const FieldDef &field, bool new_line = true) const {
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";
+ Indent + Indent + "if o != 0:" + (new_line ? "\n" : "");
}
// Begin a class declaration.
- void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ void BeginClass(const StructDef &struct_def, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += "class " + NormalizedName(struct_def) + "(object):\n";
+ code += "class " + namer_.Type(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) {
+ void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) const {
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;
+ code += "class " + namer_.Type(enum_def) + "(object):\n";
}
// Starts a new line and then indents.
- std::string GenIndents(int num) {
+ std::string GenIndents(int num) const {
return "\n" + std::string(num * Indent.length(), ' ');
}
// A single enum member.
void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
code += Indent;
- code += NormalizedName(ev);
+ code += namer_.Variant(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) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
+ const std::string struct_type = namer_.Type(struct_def);
code += Indent + "@classmethod\n";
code += Indent + "def GetRootAs";
- code += "(cls, buf, offset=0):";
+ if (parser_.opts.python_typing) {
+ code += "(cls, buf, offset: int = 0):";
+ } else {
+ 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 = " + struct_type + "()\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";
+ if (!parser_.opts.python_no_type_prefix_suffix) {
+ // Add an alias with the old name
+ code += Indent + "@classmethod\n";
+ code += Indent + "def GetRootAs" + struct_type + "(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) {
+ void InitializeExisting(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += "Init(self, buf, pos):\n";
+ if (parser_.opts.python_typing) {
+ code += "Init(self, buf: bytes, pos: int):\n";
+ } else {
+ 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) {
+ std::string *code_ptr) const {
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";
+ code += namer_.Method(field) + "Length(self)";
+ if (parser_.opts.python_typing) {
+ code += " -> int";
+ }
+ code += ":";
+ if(!IsArray(field.value.type)){
+ code += OffsetPrefix(field,false);
+ code += GenIndents(3) + "return self._tab.VectorLen(o)";
+ code += GenIndents(2) + "return 0\n\n";
+ }else{
+ code += GenIndents(2) + "return "+NumToString(field.value.type.fixed_length)+"\n\n";
+ }
}
// Determines whether a vector is none or not.
void GetVectorIsNone(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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 += namer_.Method(field) + "IsNone(self)";
+ if (parser_.opts.python_typing) {
+ code += " -> bool";
+ }
+ code += ":";
+ if(!IsArray(field.value.type)){
+ code += GenIndents(2) +
+ "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
+ "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
+ code += GenIndents(2) + "return o == 0";
+ } else {
+ //assume that we always have an array as memory is preassigned
+ code += GenIndents(2) + "return False";
+ }
code += "\n\n";
}
// Get the value of a struct's scalar.
void GetScalarFieldOfStruct(const StructDef &struct_def,
- const FieldDef &field, std::string *code_ptr) {
+ const FieldDef &field,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += namer_.Method(field);
code += "(self): return " + getter;
code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
code += NumToString(field.value.offset) + "))\n";
@@ -196,11 +230,11 @@ class PythonGenerator : public BaseGenerator {
// Get the value of a table's scalar.
void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
std::string getter = GenGetter(field.value.type);
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += namer_.Method(field);
code += "(self):";
code += OffsetPrefix(field);
getter += "o + self._tab.Pos)";
@@ -208,7 +242,9 @@ class PythonGenerator : public BaseGenerator {
if (is_bool) { getter = "bool(" + getter + ")"; }
code += Indent + Indent + Indent + "return " + getter + "\n";
std::string default_value;
- if (is_bool) {
+ if (field.IsScalarOptional()) {
+ default_value = "None";
+ } else if (is_bool) {
default_value = field.value.constant == "0" ? "False" : "True";
} else {
default_value = IsFloat(field.value.type.base_type)
@@ -221,10 +257,11 @@ class PythonGenerator : public BaseGenerator {
// Get a struct by initializing an existing struct.
// Specific to Struct.
void GetStructFieldOfStruct(const StructDef &struct_def,
- const FieldDef &field, std::string *code_ptr) {
+ const FieldDef &field,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
+ code += namer_.Method(field);
code += "(self, obj):\n";
code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
code += NumToString(field.value.offset) + ")";
@@ -233,36 +270,83 @@ class PythonGenerator : public BaseGenerator {
// Get the value of a fixed size array.
void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr, ImportMap &imports) const {
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";
+ code += namer_.Method(field);
+
+ const ImportMapEntry import_entry = {
+ GenPackageReference(field.value.type), TypeName(field)
+ };
+
+ if (parser_.opts.python_typing) {
+ const std::string return_type = ReturnType(struct_def, field);
+ code += "(self, i: int)";
+ code += " -> " + return_type + ":";
+
+ imports.insert(import_entry);
} 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";
+ code += "(self, i):";
}
+
+ if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
+ code += GenIndents(2);
+ code += "from " + import_entry.first + " import " + import_entry.second +
+ "\n";
+ }
+
+ code += GenIndents(2) + "obj = " + TypeName(field) + "()";
+ code += GenIndents(2) + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(vec_type));
+ code += ")" + GenIndents(2) + "return obj\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 GetArrayOfNonStruct(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += namer_.Method(field);
+ code += "(self, j = None):";
+ code += GenIndents(2) + "if j is None:";
+ code += GenIndents(3) + "return [" + GenGetter(field.value.type);
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(field.value.type.VectorType()));
+ code += ")) for i in range(";
+ code += "self."+namer_.Method(field)+"Length()" + ")]";
+ code += GenIndents(2) +"elif j >= 0 and j < self."+namer_.Method(field)+"Length():";
+ code += GenIndents(3) + "return " + GenGetter(field.value.type);
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + " + j * ";
+ code += NumToString(InlineSize(field.value.type.VectorType()));
+ code += "))";
+ code += GenIndents(2) + "else:";
+ code += GenIndents(3) + "return None\n\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_ptr, ImportMap &imports) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
- code += "(self):";
+ code += namer_.Method(field) + "(self)";
+
+ const ImportMapEntry import_entry = {
+ GenPackageReference(field.value.type), TypeName(field)
+ };
+
+ if (parser_.opts.python_typing) {
+ const std::string return_type = ReturnType(struct_def, field);
+ code += " -> Optional[" + return_type + "]";
+ imports.insert(ImportMapEntry{ "typing", "Optional" });
+ imports.insert(import_entry);
+ }
+ code += ":";
code += OffsetPrefix(field);
if (field.value.type.struct_def->fixed) {
code += Indent + Indent + Indent + "x = o + self._tab.Pos\n";
@@ -270,10 +354,11 @@ class PythonGenerator : public BaseGenerator {
code += Indent + Indent + Indent;
code += "x = self._tab.Indirect(o + self._tab.Pos)\n";
}
- if (parser_.opts.include_dependence_headers) {
+
+ if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
code += Indent + Indent + Indent;
- code += "from " + GenPackageReference(field.value.type) + " import " +
- TypeName(field) + "\n";
+ code += "from " + import_entry.first + " import " + import_entry.second +
+ "\n";
}
code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
@@ -283,11 +368,18 @@ class PythonGenerator : public BaseGenerator {
// Get the value of a string.
void GetStringField(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr, ImportMap &imports) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
- code += "(self):";
+ code += namer_.Method(field);
+
+ if (parser_.opts.python_typing) {
+ code += "(self) -> Optional[str]:";
+ imports.insert(ImportMapEntry{ "typing", "Optional" });
+ } else {
+ code += "(self):";
+ }
+
code += OffsetPrefix(field);
code += Indent + Indent + Indent + "return " + GenGetter(field.value.type);
code += "o + self._tab.Pos)\n";
@@ -296,21 +388,34 @@ class PythonGenerator : public BaseGenerator {
// 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_ptr, ImportMap &imports) const {
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field)) + "(self):";
- code += OffsetPrefix(field);
+ std::string return_ty = "flatbuffers.table.Table";
- // TODO(rw): this works and is not the good way to it:
bool is_native_table = TypeName(field) == "*flatbuffers.Table";
+ ImportMapEntry import_entry;
if (is_native_table) {
- code +=
- Indent + Indent + Indent + "from flatbuffers.table import Table\n";
- } else if (parser_.opts.include_dependence_headers) {
+ import_entry = ImportMapEntry{ "flatbuffers.table", "Table" };
+ } else {
+ return_ty = TypeName(field);
+ import_entry = ImportMapEntry{ GenPackageReference(field.value.type),
+ TypeName(field) };
+ }
+
+ code += namer_.Method(field) + "(self)";
+ if (parser_.opts.python_typing) {
+ code += " -> Optional[" + return_ty + "]";
+ imports.insert(ImportMapEntry{ "typing", "Optional" });
+ imports.insert(import_entry);
+ }
+ code += ":";
+ code += OffsetPrefix(field);
+
+ if (!parser_.opts.python_typing) {
code += Indent + Indent + Indent;
- code += "from " + GenPackageReference(field.value.type) + " import " +
- TypeName(field) + "\n";
+ code += "from " + import_entry.first + " import " + import_entry.second +
+ "\n";
}
code += Indent + Indent + Indent + "obj = Table(bytearray(), 0)\n";
code += Indent + Indent + Indent + GenGetter(field.value.type);
@@ -320,28 +425,38 @@ class PythonGenerator : public BaseGenerator {
// Generate the package reference when importing a struct or enum from its
// module.
- std::string GenPackageReference(const Type &type) {
- Namespace *namespaces;
+ std::string GenPackageReference(const Type &type) const {
if (type.struct_def) {
- namespaces = type.struct_def->defined_namespace;
+ return namer_.NamespacedType(*type.struct_def);
} else if (type.enum_def) {
- namespaces = type.enum_def->defined_namespace;
+ return namer_.NamespacedType(*type.enum_def);
} 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) {
+ const FieldDef &field, std::string *code_ptr,
+ ImportMap &imports) const {
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 += namer_.Method(field);
+ const ImportMapEntry import_entry = {
+ GenPackageReference(field.value.type), TypeName(field)
+ };
+
+ if (parser_.opts.python_typing) {
+ const std::string return_type = ReturnType(struct_def, field);
+ code += "(self, j: int) -> Optional[" + return_type + "]";
+ imports.insert(ImportMapEntry{ "typing", "Optional" });
+ imports.insert(import_entry);
+ } else {
+ code += "(self, j)";
+ }
+ code += ":" + 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) * ";
@@ -349,10 +464,10 @@ class PythonGenerator : public BaseGenerator {
if (!(vectortype.struct_def->fixed)) {
code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n";
}
- if (parser_.opts.include_dependence_headers) {
+ if (parser_.opts.include_dependence_headers && !parser_.opts.python_typing) {
code += Indent + Indent + Indent;
- code += "from " + GenPackageReference(field.value.type) + " import " +
- TypeName(field) + "\n";
+ code += "from " + import_entry.first + " import " + import_entry.second +
+ "\n";
}
code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
@@ -364,13 +479,18 @@ class PythonGenerator : public BaseGenerator {
// 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_ptr) const {
auto &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field));
- code += "(self, j):";
+ code += namer_.Method(field);
+ if (parser_.opts.python_typing) {
+ code += "(self, j: int)";
+ } else {
+ code += "(self, j)";
+ }
+ code += ":";
code += OffsetPrefix(field);
code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n";
code += Indent + Indent + Indent;
@@ -389,7 +509,7 @@ class PythonGenerator : public BaseGenerator {
// than iterating over the vector element by element.
void GetVectorOfNonStructAsNumpy(const StructDef &struct_def,
const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
auto vectortype = field.value.type.VectorType();
@@ -398,49 +518,76 @@ class PythonGenerator : public BaseGenerator {
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 += namer_.Method(field) + "AsNumpy(self):";
+ if(!IsArray(field.value.type)){
+ code += OffsetPrefix(field, false);
+
+ code += GenIndents(3);
+ code += "return ";
+ code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
+ code += namer_.Method(GenTypeGet(field.value.type));
+ code += "Flags, o)";
+
+ if (IsString(vectortype)) {
+ code += GenIndents(2) + "return \"\"\n";
+ } else {
+ code += GenIndents(2) + "return 0\n";
+ }
+ }else{
+ code += GenIndents(2) + "return ";
+ code += "self._tab.GetArrayAsNumpy(flatbuffers.number_types.";
+ code += namer_.Method(GenTypeGet(field.value.type.VectorType()));
+ code += "Flags, self._tab.Pos + "+NumToString(field.value.offset)+", "+NumToString("self."+namer_.Method(field)+"Length()")+")\n";
}
code += "\n";
}
+ std::string NestedFlatbufferType(std::string unqualified_name) const {
+ StructDef *nested_root = parser_.LookupStruct(unqualified_name);
+ std::string qualified_name;
+ if (nested_root == nullptr) {
+ qualified_name = namer_.NamespacedType(
+ parser_.current_namespace_->components, unqualified_name);
+ // Double check qualified name just to be sure it exists.
+ nested_root = parser_.LookupStruct(qualified_name);
+ }
+ FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
+ return qualified_name;
+ }
+
// Returns a nested flatbuffer as itself.
void GetVectorAsNestedFlatbuffer(const StructDef &struct_def,
- const FieldDef &field,
- std::string *code_ptr) {
+ const FieldDef &field, std::string *code_ptr,
+ ImportMap &imports) const {
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);
+ const std::string unqualified_name = nested->constant;
+ std::string qualified_name = NestedFlatbufferType(unqualified_name);
+ if (qualified_name.empty()) {
+ qualified_name = nested->constant;
}
- FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
- (void)nested_root;
+
+ const ImportMapEntry import_entry = { qualified_name,
+ unqualified_name };
auto &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
- code += MakeCamel(NormalizedName(field)) + "NestedRoot(self):";
+ code += namer_.Method(field) + "NestedRoot(self)";
+ if (parser_.opts.python_typing) {
+ code += " -> Union[" + unqualified_name + ", int]";
+ imports.insert(ImportMapEntry{ "typing", "Union" });
+ imports.insert(import_entry);
+ }
+ code += ":";
code += OffsetPrefix(field);
- code += Indent + Indent + Indent;
- code += "from " + qualified_name + " import " + unqualified_name + "\n";
+ if (!parser_.opts.python_typing) {
+ code += Indent + Indent + Indent;
+ code += "from " + import_entry.first + " import " + import_entry.second +
+ "\n";
+ }
code += Indent + Indent + Indent + "return " + unqualified_name;
code += ".GetRootAs";
code += "(self._tab.Bytes, self._tab.Vector(o))\n";
@@ -449,11 +596,12 @@ class PythonGenerator : public BaseGenerator {
}
// Begin the creator function signature.
- void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
+ void BeginBuilderArgs(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
code += "\n";
- code += "def Create" + NormalizedName(struct_def);
+ code += "def Create" + namer_.Type(struct_def);
code += "(builder";
}
@@ -463,7 +611,7 @@ class PythonGenerator : public BaseGenerator {
const std::string nameprefix,
const std::string namesuffix, bool has_field_name,
const std::string fieldname_suffix,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
@@ -476,21 +624,21 @@ class PythonGenerator : public BaseGenerator {
// a nested struct, prefix the name with the field name.
auto subprefix = nameprefix;
if (has_field_name) {
- subprefix += NormalizedName(field) + fieldname_suffix;
+ subprefix += namer_.Field(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); }
+ if (has_field_name) { code += namer_.Field(field); }
code += namesuffix;
}
}
}
// End the creator function signature.
- void EndBuilderArgs(std::string *code_ptr) {
+ void EndBuilderArgs(std::string *code_ptr) const {
auto &code = *code_ptr;
code += "):\n";
}
@@ -499,7 +647,7 @@ class PythonGenerator : public BaseGenerator {
// padding.
void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
std::string *code_ptr, size_t index = 0,
- bool in_array = false) {
+ bool in_array = false) const {
auto &code = *code_ptr;
std::string indent(index * 4, ' ');
code +=
@@ -516,7 +664,7 @@ class PythonGenerator : public BaseGenerator {
indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field_type)) {
StructBuilderBody(*field_type.struct_def,
- (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ (nameprefix + (namer_.Field(field) + "_")).c_str(),
code_ptr, index, in_array);
} else {
const auto index_var = "_idx" + NumToString(index);
@@ -527,14 +675,13 @@ class PythonGenerator : public BaseGenerator {
in_array = true;
}
if (IsStruct(type)) {
- StructBuilderBody(
- *field_type.struct_def,
- (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr,
- index + 1, in_array);
+ StructBuilderBody(*field_type.struct_def,
+ (nameprefix + (namer_.Field(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);
+ code += nameprefix + namer_.Variable(field);
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]";
@@ -545,108 +692,138 @@ class PythonGenerator : public BaseGenerator {
}
}
- void EndBuilderBody(std::string *code_ptr) {
+ void EndBuilderBody(std::string *code_ptr) const {
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) {
+ void GetStartOfTable(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- code += "def Start(builder): ";
- code += "builder.StartObject(";
+ const auto struct_type = namer_.Type(struct_def);
+ // Generate method with struct name.
+
+ const auto name = parser_.opts.python_no_type_prefix_suffix ? "Start" : struct_type + "Start";
+
+ code += "def " + name;
+ if (parser_.opts.python_typing) {
+ code += "(builder: flatbuffers.Builder):\n";
+ } else {
+ code += "(builder):\n";
+ }
+
+ code += Indent + "builder.StartObject(";
code += NumToString(struct_def.fields.vec.size());
- code += ")\n";
+ code += ")\n\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";
+ if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
+ // Generate method without struct name.
+ if (parser_.opts.python_typing) {
+ code += "def Start(builder: flatbuffers.Builder):\n";
+ } else {
+ code += "def Start(builder):\n";
+ }
+ code += Indent + struct_type + "Start(builder)\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) {
+ const size_t offset, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += "def Add" + MakeCamel(NormalizedName(field));
- code += "(builder, ";
- code += MakeCamel(NormalizedName(field), false);
- code += "): ";
- code += "builder.Prepend";
+ const std::string field_var = namer_.Variable(field);
+ const std::string field_method = namer_.Method(field);
+ const std::string field_ty = GenFieldTy(field);
+
+ const auto name = parser_.opts.python_no_type_prefix_suffix ? "Add" + field_method : namer_.Type(struct_def) + "Add" + field_method;
+
+ // Generate method with struct name.
+ code += "def " + name;
+ if (parser_.opts.python_typing) {
+ code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
+ } else {
+ code += "(builder, " + field_var;
+ }
+ code += "):\n";
+ code += Indent + "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) + ")";
+ code += "(" + field_var + ")";
} else {
- code += MakeCamel(NormalizedName(field), false);
+ code += field_var;
}
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";
+ if (field.IsScalarOptional()) {
+ code += "None";
+ } else if (IsFloat(field.value.type.base_type)) {
+ code += float_const_gen_.GenFloatConstant(field);
+ } else {
+ code += field.value.constant;
+ }
+ code += ")\n\n";
- // Add alias with the old name.
+ if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
+ // Generate method without struct name.
+ code += "def Add" + field_method + "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty + "):\n";
+ code +=
+ Indent + namer_.Type(struct_def) + "Add" + field_method;
+ code += "(builder, ";
+ code += field_var;
+ 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_ptr) const {
auto &code = *code_ptr;
- code += "def Start";
- code += MakeCamel(NormalizedName(field));
- code += "Vector(builder, numElems): return builder.StartVector(";
+ const std::string struct_type = namer_.Type(struct_def);
+ const std::string field_method = namer_.Method(field);
+
+ // Generate method with struct name.
+ const auto name = parser_.opts.python_no_type_prefix_suffix ? "Start" + field_method : struct_type + "Start" + field_method;
+ code += "def " + name;
+ if (parser_.opts.python_typing) {
+ code += "Vector(builder, numElems: int) -> int:\n";
+ } else {
+ code += "Vector(builder, numElems):\n";
+ }
+
+ code += Indent + "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";
+ code += ")\n\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";
+ if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
+ // Generate method without struct name.
+ code += "def Start" + field_method + "Vector(builder, numElems: int) -> int:\n";
+ code += Indent + "return " + struct_type + "Start";
+ code += field_method + "Vector(builder, numElems)\n\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) {
+ void BuildVectorOfTableFromBytes(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) const {
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";
+ const std::string field_method = namer_.Method(field);
+ const std::string struct_type = namer_.Type(struct_def);
+
+ // Generate method with struct and field name.
+ code += "def " + struct_type + "Make" + field_method;
+ code += "VectorFromBytes(builder, bytes):\n";
code += Indent + "builder.StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
@@ -659,40 +836,50 @@ class PythonGenerator : public BaseGenerator {
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";
+ if (!parser_.opts.one_file) {
+ // Generate method without struct and field name.
+ code += "def Make" + field_method + "VectorFromBytes(builder, bytes):\n";
+ code += Indent + "return " + struct_type + "Make" + field_method +
+ "VectorFromBytes(builder, bytes)\n";
+ }
}
// Get the offset of the end of a table.
- void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
+ void GetEndOffsetOnTable(const StructDef &struct_def,
+ std::string *code_ptr) const {
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)";
+ const auto name = parser_.opts.python_no_type_prefix_suffix ? "End" : namer_.Type(struct_def) + "End";
+ // Generate method with struct name.
+ if (parser_.opts.python_typing) {
+ code += "def " + name + "(builder: flatbuffers.Builder) -> int:\n";
+ } else {
+ code += "def " + name + "(builder):\n";
+ }
+ code += Indent + "return builder.EndObject()\n\n";
+
+ if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
+ // Generate method without struct name.
+ if (parser_.opts.python_typing) {
+ code += "def End(builder: flatbuffers.Builder) -> int:\n";
+ } else {
+ code += "def End(builder):\n";
+ }
+ code += Indent + "return " + namer_.Type(struct_def) + "End(builder)";
+ code += "\n";
+ }
}
// Generate the receiver for function signatures.
- void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+ void GenReceiver(const StructDef &struct_def, std::string *code_ptr) const {
auto &code = *code_ptr;
- code += Indent + "# " + NormalizedName(struct_def) + "\n";
+ code += Indent + "# " + namer_.Type(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) {
+ std::string *code_ptr, ImportMap &imports) const {
GenComment(field.doc_comment, code_ptr, &def_comment, Indent.c_str());
if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) {
@@ -700,32 +887,41 @@ class PythonGenerator : public BaseGenerator {
} 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);
+ GetStructFieldOfTable(struct_def, field, code_ptr, imports);
}
break;
case BASE_TYPE_STRING:
- GetStringField(struct_def, field, code_ptr);
+ GetStringField(struct_def, field, code_ptr, imports);
break;
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
- GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr, imports);
} else {
GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
- GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr);
+ GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetArrayOfStruct(struct_def, field, code_ptr, imports);
+ } else {
+ GetArrayOfNonStruct(struct_def, field, code_ptr);
+ GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
+ GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
}
break;
}
- case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+ case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr, imports); break;
default: FLATBUFFERS_ASSERT(0);
}
}
@@ -736,17 +932,23 @@ class PythonGenerator : public BaseGenerator {
}
// Generate struct sizeof.
- void GenStructSizeOf(const StructDef &struct_def, std::string *code_ptr) {
+ void GenStructSizeOf(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
code += Indent + "@classmethod\n";
- code += Indent + "def SizeOf(cls):\n";
+ if (parser_.opts.python_typing) {
+ code += Indent + "def SizeOf(cls) -> int:\n";
+ } else {
+ 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) {
+ void GenTableBuilders(const StructDef &struct_def,
+ std::string *code_ptr) const {
GetStartOfTable(struct_def, code_ptr);
for (auto it = struct_def.fields.vec.begin();
@@ -758,7 +960,7 @@ class PythonGenerator : public BaseGenerator {
BuildFieldOfTable(struct_def, field, offset, code_ptr);
if (IsVector(field.value.type)) {
BuildVectorOfTable(struct_def, field, code_ptr);
- BuildVectorOfTableFromBytes(field, code_ptr);
+ BuildVectorOfTableFromBytes(struct_def, field, code_ptr);
}
}
@@ -767,7 +969,7 @@ class PythonGenerator : public BaseGenerator {
// Generate function to check for proper file identifier
void GenHasFileIdentifier(const StructDef &struct_def,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
std::string escapedID;
// In the event any of file_identifier characters are special(NULL, \, etc),
@@ -779,7 +981,7 @@ class PythonGenerator : public BaseGenerator {
}
code += Indent + "@classmethod\n";
- code += Indent + "def " + NormalizedName(struct_def);
+ code += Indent + "def " + namer_.Type(struct_def);
code += "BufferHasIdentifier(cls, buf, offset, size_prefixed=False):";
code += "\n";
code += Indent + Indent;
@@ -790,7 +992,8 @@ class PythonGenerator : public BaseGenerator {
}
// Generates struct or table methods.
- void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr,
+ ImportMap &imports) const {
if (struct_def.generated) return;
GenComment(struct_def.doc_comment, code_ptr, &def_comment);
@@ -815,7 +1018,7 @@ class PythonGenerator : public BaseGenerator {
auto &field = **it;
if (field.deprecated) continue;
- GenStructAccessor(struct_def, field, code_ptr);
+ GenStructAccessor(struct_def, field, code_ptr, imports);
}
if (struct_def.fixed) {
@@ -828,23 +1031,24 @@ class PythonGenerator : public BaseGenerator {
}
void GenReceiverForObjectAPI(const StructDef &struct_def,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- code += GenIndents(1) + "# " + NormalizedName(struct_def) + "T";
+ code += GenIndents(1) + "# " + namer_.ObjectType(struct_def);
code += GenIndents(1) + "def ";
}
void BeginClassForObjectAPI(const StructDef &struct_def,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
code += "\n";
- code += "class " + NormalizedName(struct_def) + "T(object):";
+ code += "class " + namer_.ObjectType(struct_def) + "(object):";
code += "\n";
}
// Gets the accoresponding python builtin type of a BaseType for scalars and
// string.
- std::string GetBasePythonTypeForScalarAndString(const BaseType &base_type) {
+ std::string GetBasePythonTypeForScalarAndString(
+ const BaseType &base_type) const {
if (IsBool(base_type)) {
return "bool";
} else if (IsFloat(base_type)) {
@@ -859,9 +1063,11 @@ class PythonGenerator : public BaseGenerator {
}
}
- std::string GetDefaultValue(const FieldDef &field) {
+ std::string GetDefaultValue(const FieldDef &field) const {
BaseType base_type = field.value.type.base_type;
- if (IsBool(base_type)) {
+ if (field.IsScalarOptional()) {
+ return "None";
+ } else if (IsBool(base_type)) {
return field.value.constant == "0" ? "False" : "True";
} else if (IsFloat(base_type)) {
return float_const_gen_.GenFloatConstant(field);
@@ -875,7 +1081,7 @@ class PythonGenerator : public BaseGenerator {
void GenUnionInit(const FieldDef &field, std::string *field_types_ptr,
std::set<std::string> *import_list,
- std::set<std::string> *import_typing_list) {
+ std::set<std::string> *import_typing_list) const {
// Gets all possible types in the union.
import_typing_list->insert("Union");
auto &field_types = *field_types_ptr;
@@ -890,7 +1096,7 @@ class PythonGenerator : public BaseGenerator {
std::string field_type;
switch (ev.union_type.base_type) {
case BASE_TYPE_STRUCT:
- field_type = GenTypeGet(ev.union_type) + "T";
+ field_type = namer_.ObjectType(*ev.union_type.struct_def);
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(ev.union_type);
field_type = package_reference + "." + field_type;
@@ -910,45 +1116,42 @@ class PythonGenerator : public BaseGenerator {
// 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));
+ const auto package_reference = GenPackageReference(field.value.type);
import_list->insert("import " + package_reference);
}
}
- void GenStructInit(const FieldDef &field, std::string *field_type_ptr,
+ void GenStructInit(const FieldDef &field, std::string *out_ptr,
std::set<std::string> *import_list,
- std::set<std::string> *import_typing_list) {
+ std::set<std::string> *import_typing_list) const {
import_typing_list->insert("Optional");
- auto &field_type = *field_type_ptr;
+ auto &output = *out_ptr;
+ const Type &type = field.value.type;
+ const std::string object_type = namer_.ObjectType(*type.struct_def);
if (parser_.opts.include_dependence_headers) {
- auto package_reference = GenPackageReference(field.value.type);
- field_type = package_reference + "." + TypeName(field) + "T]";
+ auto package_reference = GenPackageReference(type);
+ output = package_reference + "." + object_type + "]";
import_list->insert("import " + package_reference);
} else {
- field_type = TypeName(field) + "T]";
+ output = object_type + "]";
}
- field_type = "Optional[" + field_type;
+ output = "Optional[" + output;
}
void GenVectorInit(const FieldDef &field, std::string *field_type_ptr,
std::set<std::string> *import_list,
- std::set<std::string> *import_typing_list) {
+ std::set<std::string> *import_typing_list) const {
import_typing_list->insert("List");
auto &field_type = *field_type_ptr;
- auto base_type = field.value.type.VectorType().base_type;
+ const Type &vector_type = field.value.type.VectorType();
+ const BaseType base_type = vector_type.base_type;
if (base_type == BASE_TYPE_STRUCT) {
- field_type = GenTypeGet(field.value.type.VectorType()) + "T]";
+ const std::string object_type =
+ namer_.ObjectType(*vector_type.struct_def);
+ field_type = object_type + "]";
if (parser_.opts.include_dependence_headers) {
- auto package_reference =
- GenPackageReference(field.value.type.VectorType());
- field_type = package_reference + "." +
- GenTypeGet(field.value.type.VectorType()) + "T]";
+ auto package_reference = GenPackageReference(vector_type);
+ field_type = package_reference + "." + object_type + "]";
import_list->insert("import " + package_reference);
}
field_type = "List[" + field_type;
@@ -959,7 +1162,7 @@ class PythonGenerator : public BaseGenerator {
}
void GenInitialize(const StructDef &struct_def, std::string *code_ptr,
- std::set<std::string> *import_list) {
+ std::set<std::string> *import_list) const {
std::string code;
std::set<std::string> import_typing_list;
for (auto it = struct_def.fields.vec.begin();
@@ -987,14 +1190,17 @@ class PythonGenerator : public BaseGenerator {
default:
// Scalar or sting fields.
field_type = GetBasePythonTypeForScalarAndString(base_type);
+ if (field.IsScalarOptional()) {
+ field_type = "Optional[" + field_type + "]";
+ }
break;
}
- auto default_value = GetDefaultValue(field);
+ const 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;
+ const auto field_field = namer_.Field(field);
+ code += GenIndents(2) + "self." + field_field + " = " + default_value +
+ " # type: " + field_type;
}
// Writes __init__ method.
@@ -1030,46 +1236,74 @@ class PythonGenerator : public BaseGenerator {
}
// 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;
+ auto struct_import = "import " + namer_.NamespacedType(struct_def);
import_list->erase(struct_import);
}
- void InitializeFromBuf(const StructDef &struct_def, std::string *code_ptr) {
+ void InitializeFromBuf(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto instance_name = MakeLowerCamel(struct_def);
- auto struct_name = NormalizedName(struct_def);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(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 += GenIndents(2) + struct_var + " = " + struct_type + "()";
+ code += GenIndents(2) + struct_var + ".Init(buf, pos)";
+ code += GenIndents(2) + "return cls.InitFromObj(" + struct_var + ")";
+ code += "\n";
+ }
+
+ void InitializeFromPackedBuf(const StructDef &struct_def,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(struct_def);
+
+ code += GenIndents(1) + "@classmethod";
+ code += GenIndents(1) + "def InitFromPackedBuf(cls, buf, pos=0):";
+ code += GenIndents(2) + "n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)";
+ code += GenIndents(2) + "return cls.InitFromBuf(buf, pos+n)";
code += "\n";
}
void InitializeFromObjForObject(const StructDef &struct_def,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto instance_name = MakeLowerCamel(struct_def);
- auto struct_name = NormalizedName(struct_def);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_object = namer_.ObjectType(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(1) + "def InitFromObj(cls, " + struct_var + "):";
+ code += GenIndents(2) + "x = " + struct_object + "()";
+ code += GenIndents(2) + "x._UnPack(" + struct_var + ")";
code += GenIndents(2) + "return x";
code += "\n";
}
+ void GenCompareOperator(const StructDef &struct_def,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ code += GenIndents(1) + "def __eq__(self, other):";
+ code += GenIndents(2) + "return type(self) == type(other)";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ // Wrties the comparison statement for this field.
+ const auto field_field = namer_.Field(field);
+ code += " and \\" + GenIndents(3) + "self." + field_field + " == " + "other." + field_field;
+ }
+ code += "\n";
+ }
+
void GenUnPackForStruct(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto struct_instance_name = MakeLowerCamel(struct_def);
- auto field_instance_name = MakeLowerCamel(field);
- auto field_accessor_name = MakeUpperCamel(field);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
auto field_type = TypeName(field);
if (parser_.opts.include_dependence_headers) {
@@ -1077,16 +1311,14 @@ class PythonGenerator : public BaseGenerator {
field_type = package_reference + "." + TypeName(field);
}
- code += GenIndents(2) + "if " + struct_instance_name + "." +
- field_accessor_name + "(";
+ code += GenIndents(2) + "if " + struct_var + "." + field_method + "(";
// 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 + "(";
+ code += GenIndents(3) + "self." + field_field + " = " + namer_.ObjectType(field_type) +
+ + ".InitFromObj(" + struct_var + "." + field_method + "(";
// A struct's accessor requires a struct buf instance.
if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
code += field_type + "()";
@@ -1095,82 +1327,110 @@ class PythonGenerator : public BaseGenerator {
}
void GenUnPackForUnion(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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));
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
+ const EnumDef &enum_def = *field.value.type.enum_def;
+ auto union_type = namer_.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;
+ union_type = namer_.NamespacedType(enum_def) + "." + union_type;
}
- code += GenIndents(2) + "self." + field_instance_name + " = " + union_name +
- "Creator(" + "self." + field_instance_name + "Type, " +
- struct_instance_name + "." + field_accessor_name + "())";
+ code += GenIndents(2) + "self." + field_field + " = " + union_type +
+ "Creator(" + "self." + field_field + "Type, " + struct_var + "." +
+ field_method + "())";
}
void GenUnPackForStructVector(const StructDef &struct_def,
- const FieldDef &field, std::string *code_ptr) {
+ const FieldDef &field,
+ std::string *code_ptr) const {
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]);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
+ code += GenIndents(2) + "if not " + struct_var + "." + field_method +
+ "IsNone():";
+ code += GenIndents(3) + "self." + field_field + " = []";
+ code += GenIndents(3) + "for i in range(" + struct_var + "." +
+ field_method + "Length()):";
+
+ auto field_type = TypeName(field);
+ auto one_instance = field_type + "_";
+ 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);
+ field_type = package_reference + "." + TypeName(field);
}
+ code += GenIndents(4) + "if " + struct_var + "." + field_method +
+ "(i) is None:";
+ code += GenIndents(5) + "self." + field_field + ".append(None)";
+ code += GenIndents(4) + "else:";
+ code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
+ ".InitFromObj(" + struct_var + "." + field_method + "(i))";
+ code +=
+ GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
+ }
- code += GenIndents(4) + "if " + struct_instance_name + "." +
- field_accessor_name + "(i) is None:";
- code += GenIndents(5) + "self." + field_instance_name + ".append(None)";
+ void GenUnpackForTableVector(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
+
+ code += GenIndents(2) + "if not " + struct_var + "." + field_method +
+ "IsNone():";
+ code += GenIndents(3) + "self." + field_field + " = []";
+ code += GenIndents(3) + "for i in range(" + struct_var + "." +
+ field_method + "Length()):";
+
+ auto field_type = TypeName(field);
+ auto one_instance = field_type + "_";
+ one_instance[0] = CharToLower(one_instance[0]);
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(field.value.type);
+ field_type = package_reference + "." + TypeName(field);
+ }
+ code += GenIndents(4) + "if " + struct_var + "." + field_method +
+ "(i) is None:";
+ code += GenIndents(5) + "self." + field_field + ".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 + ")";
+ code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
+ ".InitFromObj(" + struct_var + "." + field_method + "(i))";
+ code +=
+ GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
}
void GenUnpackforScalarVectorHelper(const StructDef &struct_def,
const FieldDef &field,
- std::string *code_ptr, int indents) {
+ std::string *code_ptr,
+ int indents) const {
auto &code = *code_ptr;
- auto field_instance_name = MakeLowerCamel(field);
- auto field_accessor_name = MakeUpperCamel(field);
- auto struct_instance_name = MakeLowerCamel(struct_def);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(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))";
+ code += GenIndents(indents) + "self." + field_field + " = []";
+ code += GenIndents(indents) + "for i in range(" + struct_var + "." +
+ field_method + "Length()):";
+ code += GenIndents(indents + 1) + "self." + field_field + ".append(" +
+ struct_var + "." + field_method + "(i))";
}
void GenUnPackForScalarVector(const StructDef &struct_def,
- const FieldDef &field, std::string *code_ptr) {
+ const FieldDef &field,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto field_instance_name = MakeLowerCamel(field);
- auto field_accessor_name = MakeUpperCamel(field);
- auto struct_instance_name = MakeLowerCamel(struct_def);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
- code += GenIndents(2) + "if not " + struct_instance_name + "." +
- field_accessor_name + "IsNone():";
+ code += GenIndents(2) + "if not " + struct_var + "." + field_method +
+ "IsNone():";
// String does not have the AsNumpy method.
if (!(IsScalar(field.value.type.VectorType().base_type))) {
@@ -1183,23 +1443,23 @@ class PythonGenerator : public BaseGenerator {
// 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()";
+ code += GenIndents(4) + "self." + field_field + " = " + struct_var + "." +
+ field_method + "AsNumpy()";
}
void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto field_instance_name = MakeLowerCamel(field);
- auto field_accessor_name = MakeUpperCamel(field);
- auto struct_instance_name = MakeLowerCamel(struct_def);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
- code += GenIndents(2) + "self." + field_instance_name + " = " +
- struct_instance_name + "." + field_accessor_name + "()";
+ code += GenIndents(2) + "self." + field_field + " = " + struct_var + "." +
+ field_method + "()";
}
// Generates the UnPack method for the object class.
- void GenUnPack(const StructDef &struct_def, std::string *code_ptr) {
+ void GenUnPack(const StructDef &struct_def, std::string *code_ptr) const {
std::string code;
// Items that needs to be imported. No duplicate modules will be imported.
std::set<std::string> import_list;
@@ -1219,6 +1479,7 @@ class PythonGenerator : public BaseGenerator {
GenUnPackForUnion(struct_def, field, &code);
break;
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -1228,22 +1489,17 @@ class PythonGenerator : public BaseGenerator {
}
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);
+ const auto struct_var = namer_.Variable(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 += "_UnPack(self, " + struct_var + "):";
+ code_base += GenIndents(2) + "if " + struct_var + " is None:";
code_base += GenIndents(3) + "return";
// Write the import statements.
@@ -1257,13 +1513,14 @@ class PythonGenerator : public BaseGenerator {
code_base += "\n";
}
- void GenPackForStruct(const StructDef &struct_def, std::string *code_ptr) {
+ void GenPackForStruct(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto struct_name = MakeUpperCamel(struct_def);
+ const auto struct_fn = namer_.Function(struct_def);
GenReceiverForObjectAPI(struct_def, code_ptr);
code += "Pack(self, builder):";
- code += GenIndents(2) + "return Create" + struct_name + "(builder";
+ code += GenIndents(2) + "return Create" + struct_fn + "(builder";
StructBuilderArgs(struct_def,
/* nameprefix = */ "self.",
@@ -1276,65 +1533,61 @@ class PythonGenerator : public BaseGenerator {
void GenPackForStructVectorField(const StructDef &struct_def,
const FieldDef &field,
std::string *code_prefix_ptr,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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);
+ const auto field_field = namer_.Field(field);
+ const auto struct_type = namer_.Type(struct_def);
+ const auto field_method = namer_.Method(field);
// Creates the field.
- code_prefix +=
- GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code_prefix += GenIndents(2) + "if self." + field_field + " 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) + struct_type + "Start" + field_method +
+ "Vector(builder, len(self." + field_field + "))";
code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
- field_instance_name + "))):";
+ field_field + "))):";
code_prefix +=
- GenIndents(4) + "self." + field_instance_name + "[i].Pack(builder)";
- code_prefix +=
- GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ GenIndents(4) + "self." + field_field + "[i].Pack(builder)";
+ code_prefix += GenIndents(3) + field_field + " = 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) + field_field + "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 += "for i in range(len(self." + field_field + ")):";
+ code_prefix += GenIndents(4) + field_field + "list.append(self." +
+ field_field + "[i].Pack(builder))";
- code_prefix += GenIndents(3) + "Start" +
- field_accessor_name + "Vector(builder, len(self." +
- field_instance_name + "))";
+ code_prefix += GenIndents(3) + struct_type + "Start" + field_method +
+ "Vector(builder, len(self." + field_field + "))";
code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
- field_instance_name + "))):";
+ field_field + "))):";
code_prefix += GenIndents(4) + "builder.PrependUOffsetTRelative" + "(" +
- field_instance_name + "list[i])";
- code_prefix +=
- GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ field_field + "list[i])";
+ code_prefix += GenIndents(3) + field_field + " = 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 + ")";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
+ code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
+ field_field + ")";
}
void GenPackForScalarVectorFieldHelper(const StructDef &struct_def,
const FieldDef &field,
- std::string *code_ptr, int indents) {
+ std::string *code_ptr,
+ int indents) const {
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();
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(struct_def);
+ const auto vectortype = field.value.type.VectorType();
- code += GenIndents(indents) + "Start" + field_accessor_name +
- "Vector(builder, len(self." + field_instance_name + "))";
+ code += GenIndents(indents) + struct_type + "Start" + field_method +
+ "Vector(builder, len(self." + field_field + "))";
code += GenIndents(indents) + "for i in reversed(range(len(self." +
- field_instance_name + "))):";
+ field_field + "))):";
code += GenIndents(indents + 1) + "builder.Prepend";
std::string type_name;
@@ -1359,118 +1612,109 @@ class PythonGenerator : public BaseGenerator {
void GenPackForScalarVectorField(const StructDef &struct_def,
const FieldDef &field,
std::string *code_prefix_ptr,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(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 + ")";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
+ code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
+ field_field + ")";
// Creates the field.
- code_prefix +=
- GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code_prefix += GenIndents(2) + "if self." + field_field + " 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_field + "list = []";
code_prefix +=
- GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ GenIndents(3) + "for i in range(len(self." + field_field + ")):";
+ code_prefix += GenIndents(4) + field_field +
+ "list.append(builder.CreateString(self." + field_field +
+ "[i]))";
+ GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
+ code_prefix += "(" + field_field + "list[i])";
+ code_prefix += GenIndents(3) + field_field + " = 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 +
- ")";
+ field_field + ") is np.ndarray:";
+ code_prefix += GenIndents(4) + field_field +
+ " = builder.CreateNumpyVector(self." + field_field + ")";
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()";
+ code_prefix += "(self." + field_field + "[i])";
+ code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
}
void GenPackForStructField(const StructDef &struct_def, const FieldDef &field,
std::string *code_prefix_ptr,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(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)";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
+ code += GenIndents(3) + field_field + " = self." + field_field +
+ ".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_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
+ code_prefix += GenIndents(3) + field_field + " = self." + field_field +
+ ".Pack(builder)";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
}
- code += GenIndents(3) + "Add" + field_accessor_name +
- "(builder, " + field_instance_name + ")";
+ code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
+ field_field + ")";
}
void GenPackForUnionField(const StructDef &struct_def, const FieldDef &field,
std::string *code_prefix_ptr,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
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);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_type = namer_.Type(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 + ")";
+ code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
+ code_prefix += GenIndents(3) + field_field + " = self." + field_field +
+ ".Pack(builder)";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
+ code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
+ field_field + ")";
}
- void GenPackForTable(const StructDef &struct_def, std::string *code_ptr) {
+ void GenPackForTable(const StructDef &struct_def,
+ std::string *code_ptr) const {
auto &code_base = *code_ptr;
std::string code, code_prefix;
- auto struct_instance_name = MakeLowerCamel(struct_def);
- auto struct_name = NormalizedName(struct_def);
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(struct_def);
GenReceiverForObjectAPI(struct_def, code_ptr);
code_base += "Pack(self, builder):";
- code += GenIndents(2) + "Start(builder)";
+ code += GenIndents(2) + struct_type + "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);
+ const auto field_method = namer_.Method(field);
+ const auto field_field = namer_.Field(field);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
@@ -1481,6 +1725,7 @@ class PythonGenerator : public BaseGenerator {
GenPackForUnionField(struct_def, field, &code_prefix, &code);
break;
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -1490,41 +1735,35 @@ class PythonGenerator : public BaseGenerator {
}
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 + ")";
+ code_prefix +=
+ GenIndents(2) + "if self." + field_field + " is not None:";
+ code_prefix += GenIndents(3) + field_field +
+ " = builder.CreateString(self." + field_field + ")";
+ code += GenIndents(2) + "if self." + field_field + " is not None:";
+ code += GenIndents(3) + struct_type + "Add" + field_method +
+ "(builder, " + field_field + ")";
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 + ")";
+ code += GenIndents(2) + struct_type + "Add" + field_method +
+ "(builder, self." + field_field + ")";
break;
}
}
- code += GenIndents(2) + struct_instance_name + " = " + "End(builder)";
- code += GenIndents(2) + "return " + struct_instance_name;
+ code += GenIndents(2) + struct_var + " = " + struct_type + "End(builder)";
+ code += GenIndents(2) + "return " + struct_var;
code_base += code_prefix + code;
code_base += "\n";
}
void GenStructForObjectAPI(const StructDef &struct_def,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
if (struct_def.generated) return;
std::set<std::string> import_list;
@@ -1537,8 +1776,14 @@ class PythonGenerator : public BaseGenerator {
InitializeFromBuf(struct_def, &code);
+ InitializeFromPackedBuf(struct_def, &code);
+
InitializeFromObjForObject(struct_def, &code);
+ if (parser_.opts.gen_compare) {
+ GenCompareOperator(struct_def, &code);
+ }
+
GenUnPack(struct_def, &code);
if (struct_def.fixed) {
@@ -1558,14 +1803,14 @@ class PythonGenerator : public BaseGenerator {
}
void GenUnionCreatorForStruct(const EnumDef &enum_def, const EnumVal &ev,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto union_name = NormalizedName(enum_def);
- auto field_name = NormalizedName(ev);
- auto field_type = GenTypeGet(ev.union_type) + "T";
+ const auto union_type = namer_.Type(enum_def);
+ const auto variant = namer_.Variant(ev);
+ auto field_type = namer_.ObjectType(*ev.union_type.struct_def);
- code += GenIndents(1) + "if unionType == " + union_name + "()." +
- field_name + ":";
+ code +=
+ GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(ev.union_type);
code += GenIndents(2) + "import " + package_reference;
@@ -1576,25 +1821,27 @@ class PythonGenerator : public BaseGenerator {
}
void GenUnionCreatorForString(const EnumDef &enum_def, const EnumVal &ev,
- std::string *code_ptr) {
+ std::string *code_ptr) const {
auto &code = *code_ptr;
- auto union_name = NormalizedName(enum_def);
- auto field_name = NormalizedName(ev);
+ const auto union_type = namer_.Type(enum_def);
+ const auto variant = namer_.Variant(ev);
- code += GenIndents(1) + "if unionType == " + union_name + "()." +
- field_name + ":";
+ code +=
+ GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
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) {
+ void GenUnionCreator(const EnumDef &enum_def, std::string *code_ptr) const {
+ if (enum_def.generated) return;
+
auto &code = *code_ptr;
- auto union_name = MakeUpperCamel(enum_def);
+ const auto enum_fn = namer_.Function(enum_def);
code += "\n";
- code += "def " + union_name + "Creator(unionType, table):";
+ code += "def " + enum_fn + "Creator(unionType, table):";
code += GenIndents(1) + "from flatbuffers.table import Table";
code += GenIndents(1) + "if not isinstance(table, Table):";
code += GenIndents(2) + "return None";
@@ -1617,39 +1864,63 @@ class PythonGenerator : public BaseGenerator {
}
// Generate enum declarations.
- void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ void GenEnum(const EnumDef &enum_def, std::string *code_ptr) const {
if (enum_def.generated) return;
GenComment(enum_def.doc_comment, code_ptr, &def_comment);
- BeginEnum(NormalizedName(enum_def), code_ptr);
+ BeginEnum(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) {
+ std::string GenGetter(const Type &type) const {
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, ";
+ namer_.Method(GenTypeGet(type)) + "Flags, ";
+ }
+ }
+
+ std::string GenFieldTy(const FieldDef &field) const {
+ if (IsScalar(field.value.type.base_type) || IsArray(field.value.type)) {
+ const std::string ty = GenTypeBasic(field.value.type);
+ if (ty.find("int") != std::string::npos) {
+ return "int";
+ }
+
+ if (ty.find("float") != std::string::npos) {
+ return "float";
+ }
+
+ if (ty == "bool") {
+ return "bool";
+ }
+
+ return "Any";
+ } else {
+ if (IsStruct(field.value.type)) {
+ return "Any";
+ } else {
+ return "int";
+ }
}
}
// Returns the method name for use with add/put calls.
- std::string GenMethod(const FieldDef &field) {
+ std::string GenMethod(const FieldDef &field) const {
return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
- ? MakeCamel(GenTypeBasic(field.value.type))
+ ? namer_.Method(GenTypeBasic(field.value.type))
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
}
- std::string GenTypeBasic(const Type &type) {
+ std::string GenTypeBasic(const Type &type) const {
// clang-format off
static const char *ctypename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
@@ -1663,10 +1934,12 @@ class PythonGenerator : public BaseGenerator {
: type.base_type];
}
- std::string GenTypePointer(const Type &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_VECTOR:
+ // fall through
+ case BASE_TYPE_ARRAY: return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT: return type.struct_def->name;
case BASE_TYPE_UNION:
// fall through
@@ -1674,16 +1947,42 @@ class PythonGenerator : public BaseGenerator {
}
}
- std::string GenTypeGet(const Type &type) {
+ std::string GenTypeGet(const Type &type) const {
return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
}
- std::string TypeName(const FieldDef &field) {
+ std::string TypeName(const FieldDef &field) const {
return GenTypeGet(field.value.type);
}
+ std::string ReturnType(const StructDef &struct_def,
+ const FieldDef &field) const {
+ // If we have a class member that returns an instance of the same class,
+ // for example:
+ // class Field(object):
+ // def Children(self, j: int) -> Optional[Field]:
+ // pass
+ //
+ // we need to quote the return type:
+ // class Field(object):
+ // def Children(self, j: int) -> Optional['Field']:
+ // pass
+ //
+ // because Python is unable to resolve the name during parse and will return
+ // an error.
+ // (see PEP 484 under forward references:
+ // https://peps.python.org/pep-0484/#forward-references)
+ const std::string self_type = struct_def.name;
+ std::string field_type = TypeName(field);
+
+ if (self_type == field_type) { field_type = "'" + field_type + "'"; }
+
+ return field_type;
+ }
+
// Create a struct with a builder and the struct's arguments.
- void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
+ void GenStructBuilder(const StructDef &struct_def,
+ std::string *code_ptr) const {
BeginBuilderArgs(struct_def, code_ptr);
StructBuilderArgs(struct_def,
/* nameprefix = */ "",
@@ -1697,13 +1996,24 @@ class PythonGenerator : public BaseGenerator {
}
bool generate() {
- if (!generateEnums()) return false;
- if (!generateStructs()) return false;
+ std::string one_file_code;
+ ImportMap one_file_imports;
+ if (!generateEnums(&one_file_code)) return false;
+ if (!generateStructs(&one_file_code, one_file_imports)) return false;
+
+ if (parser_.opts.one_file) {
+ const std::string mod = file_name_ + "_generated";
+
+ // Legacy file format uses keep casing.
+ return SaveType(mod + ".py", *parser_.current_namespace_, one_file_code,
+ one_file_imports, mod, true);
+ }
+
return true;
}
private:
- bool generateEnums() {
+ bool generateEnums(std::string *one_file_code) const {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
@@ -1712,63 +2022,115 @@ class PythonGenerator : public BaseGenerator {
if (parser_.opts.generate_object_based_api & enum_def.is_union) {
GenUnionCreator(enum_def, &enumcode);
}
- if (!SaveType(enum_def, enumcode, false)) return false;
+
+ if (parser_.opts.one_file && !enumcode.empty()) {
+ *one_file_code += enumcode + "\n\n";
+ } else {
+ ImportMap imports;
+ const std::string mod =
+ namer_.File(enum_def, SkipFile::SuffixAndExtension);
+
+ if (!SaveType(namer_.File(enum_def, SkipFile::Suffix),
+ *enum_def.defined_namespace, enumcode, imports, mod,
+ false))
+ return false;
+ }
}
return true;
}
- bool generateStructs() {
+ bool generateStructs(std::string *one_file_code,
+ ImportMap &one_file_imports) const {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
std::string declcode;
- GenStruct(struct_def, &declcode);
+ ImportMap imports;
+ GenStruct(struct_def, &declcode, imports);
if (parser_.opts.generate_object_based_api) {
GenStructForObjectAPI(struct_def, &declcode);
}
- if (!SaveType(struct_def, declcode, true)) return false;
+
+ if (parser_.opts.one_file) {
+ if (!declcode.empty()) {
+ *one_file_code += declcode + "\n\n";
+ }
+
+ for (auto import_str: imports) {
+ one_file_imports.insert(import_str);
+ }
+ } else {
+ const std::string mod =
+ namer_.File(struct_def, SkipFile::SuffixAndExtension);
+ if (!SaveType(namer_.File(struct_def, SkipFile::Suffix),
+ *struct_def.defined_namespace, declcode, imports, mod,
+ 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_ptr, const std::string &mod,
+ const ImportMap &imports) const {
auto &code = *code_ptr;
code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
code += "# namespace: " + name_space_name + "\n\n";
+
if (needs_imports) {
+ const std::string local_import = "." + mod;
+
code += "import flatbuffers\n";
code += "from flatbuffers.compat import import_numpy\n";
+ if (parser_.opts.python_typing) {
+ code += "from typing import Any\n";
+
+ for (auto import_entry : imports) {
+ // If we have a file called, say, "MyType.py" and in it we have a
+ // class "MyType", we can generate imports -- usually when we
+ // have a type that contains arrays of itself -- of the type
+ // "from .MyType import MyType", which Python can't resolve. So
+ // if we are trying to import ourself, we skip.
+ if (import_entry.first != local_import) {
+ code += "from " + import_entry.first + " import " +
+ import_entry.second + "\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) {
+ bool SaveType(const std::string &defname, const Namespace &ns,
+ const std::string &classcode, const ImportMap &imports,
+ const std::string &mod, bool needs_imports) const {
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);
+ BeginFile(LastNamespacePart(ns), needs_imports, &code, mod, imports);
code += classcode;
- std::string filename =
- NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".py";
+
+ const std::string directories =
+ parser_.opts.one_file ? path_ : namer_.Directories(ns.components);
+ EnsureDirExists(directories);
+
+ for (size_t i = path_.size() + 1; i != std::string::npos;
+ i = directories.find(kPathSeparator, i + 1)) {
+ const std::string init_py =
+ directories.substr(0, i) + kPathSeparator + "__init__.py";
+ SaveFile(init_py.c_str(), "", false);
+ }
+
+ const std::string filename = directories + defname;
return SaveFile(filename.c_str(), code, false);
}
private:
- std::unordered_set<std::string> keywords_;
const SimpleFloatConstantGenerator float_const_gen_;
+ const IdlNamer namer_;
};
} // namespace python
@@ -1779,4 +2141,58 @@ bool GeneratePython(const Parser &parser, const std::string &path,
return generator.generate();
}
+namespace {
+
+class PythonCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GeneratePython(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GeneratePythonGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kPython; }
+
+ std::string LanguageName() const override { return "Python"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewPythonCodeGenerator() {
+ return std::unique_ptr<PythonCodeGenerator>(new PythonCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_python.h b/contrib/libs/flatbuffers/src/idl_gen_python.h
new file mode 100644
index 0000000000..cd0cf9f4fd
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_python.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_PYTHON_H_
+#define FLATBUFFERS_IDL_GEN_PYTHON_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Python code generator.
+std::unique_ptr<CodeGenerator> NewPythonCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_PYTHON_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_rust.cpp b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
index 455780cd94..ac6097faae 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
@@ -16,39 +16,129 @@
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_rust.h"
+
+#include <cmath>
+
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.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;
+namespace {
+
+static Namer::Config RustDefaultConfig() {
+ // Historical note: We've been using "keep" casing since the original
+ // implementation, presumably because Flatbuffers schema style and Rust style
+ // roughly align. We are not going to enforce proper casing since its an
+ // unnecessary breaking change.
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kScreamingSnake,
+ /*methods=*/Case::kSnake,
+ /*functions=*/Case::kSnake,
+ /*fields=*/Case::kKeep,
+ /*variables=*/Case::kUnknown, // Unused.
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"::",
+ /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
+ /*namespaces=*/Case::kSnake,
+ /*namespace_seperator=*/"::",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kSnake,
+ /*directories=*/Case::kSnake,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".rs" };
}
-// 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;
+static std::set<std::string> RustKeywords() {
+ return {
+ // https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
+ "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",
+ // Terms that we use ourselves
+ "follow",
+ "push",
+ "size",
+ "alignment",
+ "to_little_endian",
+ "from_little_endian",
+ "ENUM_MAX",
+ "ENUM_MIN",
+ "ENUM_VALUES",
+ };
}
// Encapsulate all logical field types in this enum. This allows us to write
@@ -88,7 +178,7 @@ enum FullType {
};
// Convert a Type to a FullType (exhaustive).
-FullType GetFullType(const Type &type) {
+static FullType GetFullType(const Type &type) {
// N.B. The order of these conditionals matters for some types.
if (IsString(type)) {
@@ -178,37 +268,81 @@ FullType GetFullType(const Type &type) {
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) {
+static 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) {
+static bool IsOptionalToBuilder(const FieldDef &field) {
return field.IsOptional() || !IsScalar(field.value.type.base_type);
}
+} // namespace
+
+bool GenerateRustModuleRootFile(const Parser &parser,
+ const std::string &output_dir) {
+ if (!parser.opts.rust_module_root_file) {
+ // Don't generate a root file when generating one file. This isn't an error
+ // so return true.
+ return true;
+ }
+ Namer namer(WithFlagOptions(RustDefaultConfig(), parser.opts, output_dir),
+ RustKeywords());
+ // We gather the symbols into a tree of namespaces (which are rust mods) and
+ // generate a file that gathers them all.
+ struct Module {
+ std::map<std::string, Module> sub_modules;
+ std::vector<std::string> generated_files;
+ // Add a symbol into the tree.
+ void Insert(const Namer &namer, const Definition *s) {
+ const Definition &symbol = *s;
+ Module *current_module = this;
+ for (auto it = symbol.defined_namespace->components.begin();
+ it != symbol.defined_namespace->components.end(); it++) {
+ std::string ns_component = namer.Namespace(*it);
+ current_module = &current_module->sub_modules[ns_component];
+ }
+ current_module->generated_files.push_back(
+ namer.File(symbol.name, SkipFile::Extension));
+ }
+ // Recursively create the importer file.
+ void GenerateImports(CodeWriter &code) {
+ for (auto it = sub_modules.begin(); it != sub_modules.end(); it++) {
+ code += "pub mod " + it->first + " {";
+ code.IncrementIdentLevel();
+ code += "use super::*;";
+ it->second.GenerateImports(code);
+ code.DecrementIdentLevel();
+ code += "} // " + it->first;
+ }
+ for (auto it = generated_files.begin(); it != generated_files.end();
+ it++) {
+ code += "mod " + *it + ";";
+ code += "pub use self::" + *it + "::*;";
+ }
+ }
+ };
+ Module root_module;
+ for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
+ it++) {
+ root_module.Insert(namer, *it);
+ }
+ for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
+ it++) {
+ root_module.Insert(namer, *it);
+ }
+ CodeWriter code(" ");
+ // TODO(caspern): Move generated warning out of BaseGenerator.
+ code +=
+ "// Automatically generated by the Flatbuffers compiler. "
+ "Do not modify.";
+ code += "// @generated";
+ root_module.GenerateImports(code);
+ const bool success =
+ SaveFile((output_dir + "mod.rs").c_str(), code.ToString(), false);
+ code.Clear();
+ return success;
+}
namespace rust {
@@ -217,118 +351,87 @@ class RustGenerator : public BaseGenerator {
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);
+ cur_name_space_(nullptr),
+ namer_(WithFlagOptions(RustDefaultConfig(), parser.opts, path),
+ RustKeywords()) {
+ // TODO: Namer flag overrides should be in flatc or flatc_main.
+ code_.SetPadding(" ");
+ }
+
+ bool generate() {
+ if (!parser_.opts.rust_module_root_file) {
+ return GenerateOneFile();
+ } else {
+ return GenerateIndividualFiles();
+ }
+ }
+
+ template<typename T>
+ bool GenerateSymbols(const SymbolTable<T> &symbols,
+ std::function<void(const T &)> gen_symbol) {
+ for (auto it = symbols.vec.begin(); it != symbols.vec.end(); it++) {
+ const T &symbol = **it;
+ if (symbol.generated) continue;
+ code_.Clear();
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning());
+ code_ += "// @generated";
+ code_ += "extern crate alloc;";
+ code_ += "extern crate flatbuffers;";
+ code_ += "use alloc::boxed::Box;";
+ code_ += "use alloc::string::{String, ToString};";
+ code_ += "use alloc::vec::Vec;";
+ code_ += "use core::mem;";
+ code_ += "use core::cmp::Ordering;";
+ if (parser_.opts.rust_serialize) {
+ code_ += "extern crate serde;";
+ code_ +=
+ "use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
+ }
+ code_ += "use self::flatbuffers::{EndianScalar, Follow};";
+ code_ += "use super::*;";
+ cur_name_space_ = symbol.defined_namespace;
+ gen_symbol(symbol);
+
+ const std::string directories =
+ namer_.Directories(*symbol.defined_namespace);
+ EnsureDirExists(directories);
+ const std::string file_path = directories + namer_.File(symbol);
+ const bool save_success =
+ SaveFile(file_path.c_str(), code_.ToString(), /*binary=*/false);
+ if (!save_success) return false;
+ }
+ return true;
+ }
+
+ bool GenerateIndividualFiles() {
+ code_.Clear();
+ // Don't bother with imports. Use absolute paths everywhere.
+ return GenerateSymbols<EnumDef>(
+ parser_.enums_, [&](const EnumDef &e) { this->GenEnum(e); }) &&
+ GenerateSymbols<StructDef>(
+ parser_.structs_, [&](const StructDef &s) {
+ if (s.fixed) {
+ this->GenStruct(s);
+ } else {
+ this->GenTable(s);
+ if (this->parser_.opts.generate_object_based_api) {
+ this->GenTableObject(s);
+ }
+ }
+ if (this->parser_.root_struct_def_ == &s) {
+ this->GenRootTableFuncs(s);
+ }
+ });
}
+ // Generates code organized by .fbs files. This is broken legacy behavior
+ // that does not work with multiple fbs files with shared namespaces.
// Iterate through all definitions we haven't generated code for (enums,
// structs, and tables) and output them to a single file.
- bool generate() {
+ bool GenerateOneFile() {
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+ code_ += "// @generated";
assert(!cur_name_space_);
@@ -399,8 +502,6 @@ class RustGenerator : public BaseGenerator {
private:
CodeWriter code_;
- std::set<std::string> keywords_;
-
// This tracks the current namespace so we can insert namespace declarations.
const Namespace *cur_name_space_;
@@ -439,25 +540,16 @@ class RustGenerator : public BaseGenerator {
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 NamespacedNativeName(const EnumDef &def) {
+ return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
}
-
- std::string Name(const Definition &def) const {
- return EscapeKeyword(def.name);
+ std::string NamespacedNativeName(const StructDef &def) {
+ return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
}
- 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));
+ return WrapInNameSpace(def.defined_namespace,
+ namer_.EscapeKeyword(def.name));
}
std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) const {
@@ -466,19 +558,6 @@ class RustGenerator : public BaseGenerator {
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
@@ -496,32 +575,25 @@ class RustGenerator : public BaseGenerator {
// 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) + "::";
- }
+ size_t common = 0;
+ std::vector<std::string> s, d;
+ if (src) s = src->components;
+ if (dst) d = dst->components;
+ while (common < s.size() && common < d.size() && s[common] == d[common])
+ common++;
+ // If src namespace is empty, this must be an absolute path.
+ for (size_t i = common; i < s.size(); i++) stream << "super::";
+ for (size_t i = common; i < d.size(); i++)
+ stream << namer_.Namespace(d[i]) + "::";
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 + "\\";
+ for (auto it = dc.begin(); it != dc.end(); it++) {
+ code_ += std::string(prefix) + "///" + *it;
+ }
}
// Return a Rust type from the table in idl.h.
@@ -608,7 +680,7 @@ class RustGenerator : public BaseGenerator {
std::string GetEnumValue(const EnumDef &enum_def,
const EnumVal &enum_val) const {
- return Name(enum_def) + "::" + Name(enum_val);
+ return namer_.EnumVariant(enum_def, enum_val);
}
// 1 suffix since old C++ can't figure out the overload.
@@ -616,9 +688,11 @@ class RustGenerator : public BaseGenerator {
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("VARIANT", namer_.Variant(ev));
code_.SetValue("VALUE", enum_def.ToString(ev));
+ code_.IncrementIdentLevel();
cb(ev);
+ code_.DecrementIdentLevel();
}
}
void ForAllEnumValues(const EnumDef &enum_def, std::function<void()> cb) {
@@ -633,10 +707,13 @@ class RustGenerator : public BaseGenerator {
// an enum match function,
// and an enum array of values
void GenEnum(const EnumDef &enum_def) {
- code_.SetValue("ENUM_NAME", Name(enum_def));
+ const bool is_private = parser_.opts.no_leak_private_annotations &&
+ (enum_def.attributes.Lookup("private") != nullptr);
+ code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
+ code_.SetValue("ENUM_TY", namer_.Type(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))));
+ code_.SetValue("ENUM_NAMESPACE", namer_.Namespace(enum_def.name));
+ code_.SetValue("ENUM_CONSTANT", namer_.Constant(enum_def.name));
const EnumVal *minv = enum_def.MinValue();
const EnumVal *maxv = enum_def.MaxValue();
FLATBUFFERS_ASSERT(minv && maxv);
@@ -649,22 +726,21 @@ class RustGenerator : public BaseGenerator {
// 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_ += "mod bitflags_{{ENUM_NAMESPACE}} {";
code_ += " flatbuffers::bitflags::bitflags! {";
GenComment(enum_def.doc_comment, " ");
code_ += " #[derive(Default)]";
- code_ += " pub struct {{ENUM_NAME}}: {{BASE_TYPE}} {";
+ code_ += " {{ACCESS_TYPE}} struct {{ENUM_TY}}: {{BASE_TYPE}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
- this->GenComment(ev.doc_comment, " ");
- code_ += " const {{VARIANT}} = {{VALUE}};";
+ this->GenComment(ev.doc_comment, " ");
+ code_ += " const {{VARIANT}} = {{VALUE}};";
});
code_ += " }";
code_ += " }";
code_ += "}";
- code_ += "pub use self::bitflags_{{ENUM_NAME_SNAKE}}::{{ENUM_NAME}};";
+ code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};";
code_ += "";
- code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
code_.SetValue("INTO_BASE", "self.bits()");
} else {
// Normal, c-modelled enums.
@@ -674,19 +750,19 @@ class RustGenerator : public BaseGenerator {
" instead. This will no longer be generated in 2021.\")]";
code_ += deprecation_warning;
code_ +=
- "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+ "pub const ENUM_MIN_{{ENUM_CONSTANT}}: {{BASE_TYPE}}"
" = {{ENUM_MIN_BASE_VALUE}};";
code_ += deprecation_warning;
code_ +=
- "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+ "pub const ENUM_MAX_{{ENUM_CONSTANT}}: {{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}}; " +
+ code_ += "pub const ENUM_VALUES_{{ENUM_CONSTANT}}: [{{ENUM_TY}}; " +
num_fields + "] = [";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
- code_ += " " + GetEnumValue(enum_def, ev) + ",";
+ code_ += namer_.EnumVariant(enum_def, ev) + ",";
});
code_ += "];";
code_ += "";
@@ -699,25 +775,25 @@ class RustGenerator : public BaseGenerator {
"#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, "
"Default)]";
code_ += "#[repr(transparent)]";
- code_ += "pub struct {{ENUM_NAME}}(pub {{BASE_TYPE}});";
+ code_ += "{{ACCESS_TYPE}} struct {{ENUM_TY}}(pub {{BASE_TYPE}});";
code_ += "#[allow(non_upper_case_globals)]";
- code_ += "impl {{ENUM_NAME}} {";
+ code_ += "impl {{ENUM_TY}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
- this->GenComment(ev.doc_comment, " ");
- code_ += " pub const {{VARIANT}}: Self = Self({{VALUE}});";
+ 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}},"; });
+ 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_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
});
code_ += " _ => None,";
code_ += " }";
@@ -725,10 +801,10 @@ class RustGenerator : public BaseGenerator {
code_ += "}";
// Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
- code_ += "impl std::fmt::Debug for {{ENUM_NAME}} {";
+ code_ += "impl core::fmt::Debug for {{ENUM_TY}} {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter) ->"
- " std::fmt::Result {";
+ " fn fmt(&self, f: &mut core::fmt::Formatter) ->"
+ " core::fmt::Result {";
code_ += " if let Some(name) = self.variant_name() {";
code_ += " f.write_str(name)";
code_ += " } else {";
@@ -737,49 +813,89 @@ class RustGenerator : public BaseGenerator {
code_ += " }";
code_ += "}";
- code_.SetValue("FROM_BASE", "Self(b)");
code_.SetValue("INTO_BASE", "self.0");
}
+ // Implement serde::Serialize
+ if (parser_.opts.rust_serialize) {
+ code_ += "impl Serialize for {{ENUM_TY}} {";
+ code_ +=
+ " fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
+ code_ += " where";
+ code_ += " S: Serializer,";
+ code_ += " {";
+ if (IsBitFlagsEnum(enum_def)) {
+ code_ += " serializer.serialize_u32(self.bits() as u32)";
+ } else {
+ code_ +=
+ " serializer.serialize_unit_variant(\"{{ENUM_TY}}\", self.0 "
+ "as "
+ "u32, self.variant_name().unwrap())";
+ }
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ }
+
// Generate Follow and Push so we can serialize and stuff.
- code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_NAME}} {";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {";
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_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
+ if (IsBitFlagsEnum(enum_def)) {
+ // Safety:
+ // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
+ // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
+ // https://github.com/bitflags/bitflags/issues/262
+ code_ += " // Safety:";
+ code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
+ code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
+ code_ += " // https://github.com/bitflags/bitflags/issues/262";
+ code_ += " Self::from_bits_unchecked(b)";
+ } else {
+ code_ += " Self(b)";
+ }
code_ += " }";
code_ += "}";
code_ += "";
- code_ += "impl flatbuffers::Push for {{ENUM_NAME}} {";
- code_ += " type Output = {{ENUM_NAME}};";
+ code_ += "impl flatbuffers::Push for {{ENUM_TY}} {";
+ code_ += " type Output = {{ENUM_TY}};";
code_ += " #[inline]";
- code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
- code_ +=
- " unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
- "(dst, {{INTO_BASE}}); }";
+ code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
+ code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, {{INTO_BASE}});";
code_ += " }";
code_ += "}";
code_ += "";
- code_ += "impl flatbuffers::EndianScalar for {{ENUM_NAME}} {";
+ code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {";
+ code_ += " type Scalar = {{BASE_TYPE}};";
code_ += " #[inline]";
- code_ += " fn to_little_endian(self) -> Self {";
- code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
- code_ += " {{FROM_BASE}}";
+ code_ += " fn to_little_endian(self) -> {{BASE_TYPE}} {";
+ code_ += " {{INTO_BASE}}.to_le()";
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_ += " fn from_little_endian(v: {{BASE_TYPE}}) -> Self {";
+ code_ += " let b = {{BASE_TYPE}}::from_le(v);";
+ if (IsBitFlagsEnum(enum_def)) {
+ // Safety:
+ // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
+ // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
+ // https://github.com/bitflags/bitflags/issues/262
+ code_ += " // Safety:";
+ code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
+ code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
+ code_ += " // https://github.com/bitflags/bitflags/issues/262";
+ code_ += " unsafe { Self::from_bits_unchecked(b) }";
+ } else {
+ code_ += " Self(b)";
+ }
code_ += " }";
code_ += "}";
code_ += "";
// Generate verifier - deferring to the base type.
- code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_NAME}} {";
+ code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_TY}} {";
code_ += " #[inline]";
code_ += " fn run_verifier(";
code_ += " v: &mut flatbuffers::Verifier, pos: usize";
@@ -790,64 +906,70 @@ class RustGenerator : public BaseGenerator {
code_ += "}";
code_ += "";
// Enums are basically integers.
- code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_NAME}} {}";
+ code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_TY}} {}";
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_.SetValue("UNION_TYPE", namer_.Type(enum_def));
+ code_ += "{{ACCESS_TYPE}} struct {{UNION_TYPE}}UnionTableOffset {}";
code_ += "";
if (parser_.opts.generate_object_based_api) { GenUnionObject(enum_def); }
}
}
- // CASPER: dedup Object versions from non object versions.
+ // TODO(cneo): 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("VARIANT_NAME", namer_.Variant(enum_val));
+ // For legacy reasons, enum variants are Keep case while enum native
+ // variants are UpperCamel case.
+ code_.SetValue("NATIVE_VARIANT",
+ namer_.LegacyRustNativeVariant(enum_val));
+ code_.SetValue("U_ELEMENT_NAME", namer_.Method(enum_val));
code_.SetValue("U_ELEMENT_TABLE_TYPE",
NamespacedNativeName(*enum_val.union_type.struct_def));
+ code_.IncrementIdentLevel();
cb();
+ code_.DecrementIdentLevel();
}
}
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));
+ code_.SetValue("ENUM_TY", namer_.Type(enum_def));
+ code_.SetValue("ENUM_FN", namer_.Function(enum_def));
+ code_.SetValue("ENUM_OTY", namer_.ObjectType(enum_def));
// Generate native union.
+ code_ += "#[allow(clippy::upper_case_acronyms)]"; // NONE's spelling is
+ // intended.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
- code_ += "pub enum {{NATIVE_NAME}} {";
+ code_ += "{{ACCESS_TYPE}} enum {{ENUM_OTY}} {";
code_ += " NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
- code_ += " {{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
+ code_ += "{{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
});
code_ += "}";
// Generate Default (NONE).
- code_ += "impl Default for {{NATIVE_NAME}} {";
+ code_ += "impl Default for {{ENUM_OTY}} {";
code_ += " fn default() -> Self {";
code_ += " Self::NONE";
code_ += " }";
code_ += "}";
// Generate native union methods.
- code_ += "impl {{NATIVE_NAME}} {";
+ code_ += "impl {{ENUM_OTY}} {";
// Get flatbuffers union key.
- // CASPER: add docstrings?
- code_ += " pub fn {{ENUM_NAME_SNAKE}}_type(&self) -> {{ENUM_NAME}} {";
+ // TODO(cneo): add docstrings?
+ code_ += " pub fn {{ENUM_FN}}_type(&self) -> {{ENUM_TY}} {";
code_ += " match self {";
- code_ += " Self::NONE => {{ENUM_NAME}}::NONE,";
+ code_ += " Self::NONE => {{ENUM_TY}}::NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ +=
- " Self::{{NATIVE_VARIANT}}(_) => {{ENUM_NAME}}::"
+ " Self::{{NATIVE_VARIANT}}(_) => {{ENUM_TY}}::"
"{{VARIANT_NAME}},";
});
code_ += " }";
@@ -860,9 +982,8 @@ class RustGenerator : public BaseGenerator {
code_ += " match self {";
code_ += " Self::NONE => None,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
- code_ +=
- " Self::{{NATIVE_VARIANT}}(v) => "
- "Some(v.pack(fbb).as_union_value()),";
+ code_ += " Self::{{NATIVE_VARIANT}}(v) => \\";
+ code_ += "Some(v.pack(fbb).as_union_value()),";
});
code_ += " }";
code_ += " }";
@@ -871,52 +992,48 @@ class RustGenerator : public BaseGenerator {
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
// Move accessor.
code_ +=
- " /// If the union variant matches, return the owned "
+ "/// 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) -> "
+ "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_ += " if let Self::{{NATIVE_VARIANT}}(_) = self {";
+ code_ += " let v = core::mem::replace(self, Self::NONE);";
+ code_ += " if let Self::{{NATIVE_VARIANT}}(w) = v {";
+ code_ += " Some(w)";
code_ += " } else {";
- code_ += " None";
+ code_ += " unreachable!()";
code_ += " }";
+ code_ += " } else {";
+ code_ += " None";
code_ += " }";
+ code_ += "}";
// Immutable reference accessor.
code_ +=
- " /// If the union variant matches, return a reference to the "
+ "/// If the union variant matches, return a reference to the "
"{{U_ELEMENT_TABLE_TYPE}}.";
code_ +=
- " pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
+ "pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
"Option<&{{U_ELEMENT_TABLE_TYPE}}> {";
code_ +=
- " if let Self::{{NATIVE_VARIANT}}(v) = self "
+ " if let Self::{{NATIVE_VARIANT}}(v) = self "
"{ Some(v.as_ref()) } else { None }";
- code_ += " }";
+ code_ += "}";
// Mutable reference accessor.
code_ +=
- " /// If the union variant matches, return a mutable reference"
+ "/// 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) -> "
+ "pub fn as_{{U_ELEMENT_NAME}}_mut(&mut self) -> "
"Option<&mut {{U_ELEMENT_TABLE_TYPE}}> {";
code_ +=
- " if let Self::{{NATIVE_VARIANT}}(v) = self "
+ " if let Self::{{NATIVE_VARIANT}}(v) = self "
"{ Some(v.as_mut()) } else { None }";
- code_ += " }";
+ 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) {
@@ -933,8 +1050,19 @@ class RustGenerator : public BaseGenerator {
if (field.IsOptional() && !IsUnion(field.value.type)) { return "None"; }
}
switch (GetFullType(field.value.type)) {
- case ftInteger:
+ case ftInteger: {
+ return field.value.constant;
+ }
case ftFloat: {
+ const std::string float_prefix =
+ (field.value.type.base_type == BASE_TYPE_FLOAT) ? "f32::" : "f64::";
+ if (StringIsFlatbufferNan(field.value.constant)) {
+ return float_prefix + "NAN";
+ } else if (StringIsFlatbufferPositiveInfinity(field.value.constant)) {
+ return float_prefix + "INFINITY";
+ } else if (StringIsFlatbufferNegativeInfinity(field.value.constant)) {
+ return float_prefix + "NEG_INFINITY";
+ }
return field.value.constant;
}
case ftBool: {
@@ -944,8 +1072,9 @@ class RustGenerator : public BaseGenerator {
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));
+ return WrapInNameSpace(
+ field.value.type.enum_def->defined_namespace,
+ namer_.EnumVariant(*field.value.type.enum_def, *ev));
}
case ftUnionValue: {
return ObjectFieldType(field, true) + "::NONE";
@@ -960,7 +1089,7 @@ class RustGenerator : public BaseGenerator {
field.IsRequired() ? "\"\"" : "\"" + field.value.constant + "\"";
if (context == kObject) return defval + ".to_string()";
if (context == kAccessor) return "&" + defval;
- FLATBUFFERS_ASSERT("Unreachable.");
+ FLATBUFFERS_ASSERT(false);
return "INVALID_CODE_GENERATION";
}
@@ -986,7 +1115,7 @@ class RustGenerator : public BaseGenerator {
return "Default::default()";
}
}
- FLATBUFFERS_ASSERT("Unreachable.");
+ FLATBUFFERS_ASSERT(false);
return "INVALID_CODE_GENERATION";
}
@@ -1329,11 +1458,7 @@ class RustGenerator : public BaseGenerator {
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);
+ return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
}
case ftVectorOfEnumKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
@@ -1342,7 +1467,7 @@ class RustGenerator : public BaseGenerator {
}
case ftVectorOfStruct: {
const auto typname = WrapInNameSpace(*type.struct_def);
- return WrapOption("&" + lifetime + " [" + typname + "]");
+ return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
}
case ftVectorOfTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
@@ -1451,7 +1576,7 @@ class RustGenerator : public BaseGenerator {
std::string GenTableAccessorFuncBody(const FieldDef &field,
const std::string &lifetime) {
- const std::string vt_offset = GetFieldOffsetName(field);
+ const std::string vt_offset = namer_.LegacyRustFieldOffsetName(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 =
@@ -1460,28 +1585,18 @@ class RustGenerator : public BaseGenerator {
: "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;
+ return "unsafe { self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
+ ", " + default_value + ")" + 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_ += " }";
+ const std::string fully_qualified_name =
+ struct_def.defined_namespace->GetFullyQualifiedName(name);
+ code_ += " pub const fn get_fully_qualified_name() -> &'static str {";
+ code_ += " \"" + fully_qualified_name + "\"";
+ code_ += " }";
code_ += "";
}
@@ -1495,12 +1610,12 @@ class RustGenerator : public BaseGenerator {
if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
code_.SetValue(
"U_ELEMENT_ENUM_TYPE",
- WrapInNameSpace(def.defined_namespace, GetEnumValue(def, ev)));
+ WrapInNameSpace(def.defined_namespace, namer_.EnumVariant(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)));
+ code_.SetValue("U_ELEMENT_NAME", namer_.Function(ev.name));
cb(ev);
}
}
@@ -1512,11 +1627,14 @@ class RustGenerator : public BaseGenerator {
// 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_NAME", namer_.LegacyRustFieldOffsetName(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
- code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD", namer_.Field(field));
code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder));
+ code_.SetValue("DISCRIMINANT", namer_.LegacyRustUnionTypeMethod(field));
+ code_.IncrementIdentLevel();
cb(field);
+ code_.DecrementIdentLevel();
};
const auto &fields = struct_def.fields.vec;
if (reversed) {
@@ -1528,58 +1646,67 @@ class RustGenerator : public BaseGenerator {
// 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)));
+
+ const bool is_private = parser_.opts.no_leak_private_annotations &&
+ (struct_def.attributes.Lookup("private") != nullptr);
+ code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
+ code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
+ code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
// Generate an offset type, the base type, the Follow impl, and the
// init_from_table impl.
- code_ += "pub enum {{OFFSET_TYPELABEL}} {}";
+ code_ += "{{ACCESS_TYPE}} enum {{STRUCT_TY}}Offset {}";
code_ += "#[derive(Copy, Clone, PartialEq)]";
code_ += "";
GenComment(struct_def.doc_comment);
- code_ += "pub struct {{STRUCT_NAME}}<'a> {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}<'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_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {";
+ code_ += " type Inner = {{STRUCT_TY}}<'a>;";
+ code_ += " #[inline]";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " Self { _tab: flatbuffers::Table::new(buf, loc) }";
+ code_ += " }";
code_ += "}";
code_ += "";
- code_ += "impl<'a> {{STRUCT_NAME}}<'a> {";
+ code_ += "impl<'a> {{STRUCT_TY}}<'a> {";
+
+ // Generate field id constants.
+ ForAllTableFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ +=
+ "pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
+ "{{OFFSET_VALUE}};";
+ });
+ code_ += "";
if (parser_.opts.generate_name_strings) {
GenFullyQualifiedNameGetter(struct_def, struct_def.name);
}
- code_ += " #[inline]";
+ code_ += " #[inline]";
code_ +=
- " pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
+ " pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> "
"Self {";
- code_ += " {{STRUCT_NAME}} { _tab: table }";
- code_ += " }";
+ code_ += " {{STRUCT_TY}} { _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_ += " #[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_TY}}Args{{MAYBE_LT}}";
+ code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'bldr>> {";
- code_ += " let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);";
+ code_ += " let mut builder = {{STRUCT_TY}}Builder::new(_fbb);";
for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
size; size /= 2) {
ForAllTableFields(
@@ -1590,23 +1717,23 @@ class RustGenerator : public BaseGenerator {
return;
if (IsOptionalToBuilder(field)) {
code_ +=
- " if let Some(x) = args.{{FIELD_NAME}} "
- "{ builder.add_{{FIELD_NAME}}(x); }";
+ " if let Some(x) = args.{{FIELD}} "
+ "{ builder.add_{{FIELD}}(x); }";
} else {
- code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
+ code_ += " builder.add_{{FIELD}}(args.{{FIELD}});";
}
},
/*reverse=*/true);
}
- code_ += " builder.finish()";
- code_ += " }";
+ 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}} {";
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
+ code_ += " pub fn unpack(&self) -> {{STRUCT_OTY}} {";
ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
const Type &type = field.value.type;
switch (GetFullType(type)) {
@@ -1614,36 +1741,33 @@ class RustGenerator : public BaseGenerator {
case ftBool:
case ftFloat:
case ftEnumKey: {
- code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}();";
+ code_ += " let {{FIELD}} = self.{{FIELD}}();";
return;
}
case ftUnionKey: return;
case ftUnionValue: {
const auto &enum_def = *type.enum_def;
- code_.SetValue("ENUM_NAME", WrapInNameSpace(enum_def));
+ code_.SetValue("ENUM_TY", 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,";
+ code_.SetValue("UNION_TYPE_METHOD",
+ namer_.LegacyRustUnionTypeMethod(field));
+
+ code_ += " let {{FIELD}} = match self.{{UNION_TYPE_METHOD}}() {";
+ code_ += " {{ENUM_TY}}::NONE => {{NATIVE_ENUM_NAME}}::NONE,";
ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
code_ +=
- " {{ENUM_NAME}}::{{VARIANT_NAME}} => "
+ " {{ENUM_TY}}::{{VARIANT_NAME}} => "
"{{NATIVE_ENUM_NAME}}::{{NATIVE_VARIANT}}(Box::new(";
+ code_ += " self.{{FIELD}}_as_{{U_ELEMENT_NAME}}()";
code_ +=
- " self.{{FIELD_NAME}}_as_"
- "{{U_ELEMENT_NAME}}()";
- code_ +=
- " .expect(\"Invalid union table, "
- "expected `{{ENUM_NAME}}::{{VARIANT_NAME}}`.\")";
- code_ += " .unpack()";
- code_ += " )),";
+ " .expect(\"Invalid union table, "
+ "expected `{{ENUM_TY}}::{{VARIANT_NAME}}`.\")";
+ code_ += " .unpack()";
+ code_ += " )),";
});
// Maybe we shouldn't throw away unknown discriminants?
- code_ += " _ => {{NATIVE_ENUM_NAME}}::NONE,";
- code_ += " };";
+ code_ += " _ => {{NATIVE_ENUM_NAME}}::NONE,";
+ code_ += " };";
return;
}
// The rest of the types need special handling based on if the field
@@ -1661,16 +1785,7 @@ class RustGenerator : public BaseGenerator {
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 ftVectorOfBool:
case ftVectorOfFloat:
case ftVectorOfEnumKey: {
code_.SetValue("EXPR", "x.into_iter().collect()");
@@ -1698,32 +1813,25 @@ class RustGenerator : public BaseGenerator {
}
}
if (field.IsOptional()) {
- code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}().map(|x| {";
- code_ += " {{EXPR}}";
- code_ += " });";
+ code_ += " let {{FIELD}} = self.{{FIELD}}().map(|x| {";
+ code_ += " {{EXPR}}";
+ code_ += " });";
} else {
- code_ += " let {{FIELD_NAME}} = {";
- code_ += " let x = self.{{FIELD_NAME}}();";
- code_ += " {{EXPR}}";
- code_ += " };";
+ code_ += " let {{FIELD}} = {";
+ code_ += " let x = self.{{FIELD}}();";
+ code_ += " {{EXPR}}";
+ code_ += " };";
}
});
- code_ += " {{OBJECT_NAME}} {";
+ code_ += " {{STRUCT_OTY}} {";
ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
- code_ += " {{FIELD_NAME}},";
+ code_ += " {{FIELD}},";
});
- code_ += " }";
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:
@@ -1741,11 +1849,14 @@ class RustGenerator : public BaseGenerator {
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_ += " }";
+ this->GenComment(field.doc_comment);
+ code_ += "#[inline]";
+ code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {";
+ code_ += " // Safety:";
+ code_ += " // Created from valid Table for this object";
+ code_ += " // which contains a valid value in this slot";
+ code_ += " " + GenTableAccessorFuncBody(field, "'a");
+ code_ += "}";
// Generate a comparison function for this field if it is a key.
if (field.key) { GenKeyFieldMethods(field); }
@@ -1763,38 +1874,43 @@ class RustGenerator : public BaseGenerator {
FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
code_.SetValue("NESTED", WrapInNameSpace(*nested_root));
- code_ += " pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> \\";
+ code_ += "pub fn {{FIELD}}_nested_flatbuffer(&'a self) -> \\";
if (field.IsRequired()) {
code_ += "{{NESTED}}<'a> {";
- code_ += " let data = self.{{FIELD_NAME}}();";
- code_ += " use flatbuffers::Follow;";
+ code_ += " let data = self.{{FIELD}}();";
+ code_ += " use flatbuffers::Follow;";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid flatbuffer in this slot";
code_ +=
- " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
- "::follow(data, 0)";
+ " unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data.bytes(), 0) }";
} else {
code_ += "Option<{{NESTED}}<'a>> {";
- code_ += " self.{{FIELD_NAME}}().map(|data| {";
- code_ += " use flatbuffers::Follow;";
+ code_ += " self.{{FIELD}}().map(|data| {";
+ code_ += " use flatbuffers::Follow;";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid flatbuffer in this slot";
code_ +=
- " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
- "::follow(data, 0)";
- code_ += " })";
+ " unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data.bytes(), 0) }";
+ code_ += " })";
}
- 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_ += "#[inline]";
+ code_ += "#[allow(non_snake_case)]";
code_ +=
- " pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> "
+ "pub fn {{FIELD}}_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
@@ -1808,24 +1924,28 @@ class RustGenerator : public BaseGenerator {
//
// To avoid this problem the type field name is used unescaped here:
code_ +=
- " if self.{{FIELD_TYPE_FIELD_NAME}}_type() == "
- "{{U_ELEMENT_ENUM_TYPE}} {";
+ " if self.{{DISCRIMINANT}}() == {{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))";
+ code_ += " let u = self.{{FIELD}}();";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid union in this slot";
+ code_ += " Some(unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })";
} else {
- code_ +=
- " self.{{FIELD_NAME}}().map("
- "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
+ code_ +=" self.{{FIELD}}().map(|t| {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid union in this slot";
+ code_ += " unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) }";
+ code_ += " })";
}
- code_ += " } else {";
- code_ += " None";
- code_ += " }";
+ code_ += " } else {";
+ code_ += " None";
code_ += " }";
+ code_ += "}";
code_ += "";
});
});
@@ -1833,7 +1953,7 @@ class RustGenerator : public BaseGenerator {
code_ += "";
// Generate Verifier;
- code_ += "impl flatbuffers::Verifiable for {{STRUCT_NAME}}<'_> {";
+ code_ += "impl flatbuffers::Verifiable for {{STRUCT_TY}}<'_> {";
code_ += " #[inline]";
code_ += " fn run_verifier(";
code_ += " v: &mut flatbuffers::Verifier, pos: usize";
@@ -1850,29 +1970,33 @@ class RustGenerator : public BaseGenerator {
// All types besides unions.
code_.SetValue("TY", FollowType(field.value.type, "'_"));
code_ +=
- "\n .visit_field::<{{TY}}>(&\"{{FIELD_NAME}}\", "
+ "\n .visit_field::<{{TY}}>(\"{{FIELD}}\", "
"Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
return;
}
// Unions.
- EnumDef &union_def = *field.value.type.enum_def;
+ const EnumDef &union_def = *field.value.type.enum_def;
code_.SetValue("UNION_TYPE", WrapInNameSpace(union_def));
+ code_.SetValue("UNION_TYPE_OFFSET_NAME",
+ namer_.LegacyRustUnionTypeOffsetName(field));
+ code_.SetValue("UNION_TYPE_METHOD",
+ namer_.LegacyRustUnionTypeMethod(field));
code_ +=
"\n .visit_union::<{{UNION_TYPE}}, _>("
- "&\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, "
- "&\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
+ "\"{{UNION_TYPE_METHOD}}\", Self::{{UNION_TYPE_OFFSET_NAME}}, "
+ "\"{{FIELD}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
"|key, v, pos| {";
- code_ += " match key {";
+ code_ += " match key {";
ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
(void)unused;
code_ +=
- " {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
+ " {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
"<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
"\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
});
- code_ += " _ => Ok(()),";
- code_ += " }";
- code_ += " })?\\";
+ code_ += " _ => Ok(()),";
+ code_ += " }";
+ code_ += " })?\\";
});
code_ += "\n .finish();";
code_ += " Ok(())";
@@ -1882,28 +2006,98 @@ class RustGenerator : public BaseGenerator {
// Generate an args struct:
code_.SetValue("MAYBE_LT",
TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
- code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Args{{MAYBE_LT}} {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
- code_ += " pub {{FIELD_NAME}}: {{PARAM_TYPE}},";
+ code_ += " pub {{FIELD}}: {{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 {";
+ code_ += "impl<'a> Default for {{STRUCT_TY}}Args{{MAYBE_LT}} {";
+ code_ += " #[inline]";
+ code_ += " fn default() -> Self {";
+ code_ += " {{STRUCT_TY}}Args {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
- code_ += " {{FIELD_NAME}}: {{BLDR_DEF_VAL}},\\";
+ code_ += " {{FIELD}}: {{BLDR_DEF_VAL}},\\";
code_ += field.IsRequired() ? " // required field" : "";
});
- code_ += " }";
code_ += " }";
+ code_ += " }";
code_ += "}";
+ code_ += "";
+
+ // Implement serde::Serialize
+ if (parser_.opts.rust_serialize) {
+ const auto numFields = struct_def.fields.vec.size();
+ code_.SetValue("NUM_FIELDS", NumToString(numFields));
+ code_ += "impl Serialize for {{STRUCT_TY}}<'_> {";
+ code_ +=
+ " fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
+ code_ += " where";
+ code_ += " S: Serializer,";
+ code_ += " {";
+ if (numFields == 0) {
+ code_ +=
+ " let s = serializer.serialize_struct(\"{{STRUCT_TY}}\", 0)?;";
+ } else {
+ code_ +=
+ " let mut s = serializer.serialize_struct(\"{{STRUCT_TY}}\", "
+ "{{NUM_FIELDS}})?;";
+ }
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ const Type &type = field.value.type;
+ if (IsUnion(type)) {
+ if (type.base_type == BASE_TYPE_UNION) {
+ const auto &enum_def = *type.enum_def;
+ code_.SetValue("ENUM_TY", WrapInNameSpace(enum_def));
+ code_.SetValue("FIELD", namer_.Field(field));
+ code_.SetValue("UNION_TYPE_METHOD",
+ namer_.LegacyRustUnionTypeMethod(field));
+
+ code_ += " match self.{{UNION_TYPE_METHOD}}() {";
+ code_ += " {{ENUM_TY}}::NONE => (),";
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ code_.SetValue("FIELD", namer_.Field(field));
+ code_ += " {{ENUM_TY}}::{{VARIANT_NAME}} => {";
+ code_ +=
+ " let f = "
+ "self.{{FIELD}}_as_{{U_ELEMENT_NAME}}()";
+ code_ +=
+ " .expect(\"Invalid union table, expected "
+ "`{{ENUM_TY}}::{{VARIANT_NAME}}`.\");";
+ code_ += " s.serialize_field(\"{{FIELD}}\", &f)?;";
+ code_ += " }";
+ });
+ code_ += " _ => unimplemented!(),";
+ code_ += " }";
+ } else {
+ code_ +=
+ " s.serialize_field(\"{{FIELD}}\", "
+ "&self.{{FIELD}}())?;";
+ }
+ } else {
+ if (field.IsOptional()) {
+ code_ += " if let Some(f) = self.{{FIELD}}() {";
+ code_ += " s.serialize_field(\"{{FIELD}}\", &f)?;";
+ code_ += " } else {";
+ code_ += " s.skip_field(\"{{FIELD}}\")?;";
+ code_ += " }";
+ } else {
+ code_ +=
+ " s.serialize_field(\"{{FIELD}}\", "
+ "&self.{{FIELD}}())?;";
+ }
+ }
+ });
+ code_ += " s.end()";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ }
// Generate a builder struct:
- code_ += "pub struct {{STRUCT_NAME}}Builder<'a: 'b, 'b> {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Builder<'a: 'b, 'b> {";
code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
code_ +=
" start_: flatbuffers::WIPOffset<"
@@ -1911,10 +2105,10 @@ class RustGenerator : public BaseGenerator {
code_ += "}";
// Generate builder functions:
- code_ += "impl<'a: 'b, 'b> {{STRUCT_NAME}}Builder<'a, 'b> {";
+ code_ += "impl<'a: 'b, 'b> {{STRUCT_TY}}Builder<'a, 'b> {";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
const bool is_scalar = IsScalar(field.value.type.base_type);
- std::string offset = GetFieldOffsetName(field);
+ std::string offset = namer_.LegacyRustFieldOffsetName(field);
// Generate functions to add data, which take one of two forms.
//
// If a value has a default:
@@ -1926,31 +2120,31 @@ class RustGenerator : public BaseGenerator {
// fn add_x(x_: type) {
// fbb_.push_slot_always::<type>(offset, x_);
// }
- code_.SetValue("FIELD_OFFSET", Name(struct_def) + "::" + offset);
+ code_.SetValue("FIELD_OFFSET", namer_.Type(struct_def) + "::" + offset);
code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
- code_ += " #[inline]";
+ code_ += "#[inline]";
code_ +=
- " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
+ "pub fn add_{{FIELD}}(&mut self, {{FIELD}}: "
"{{FIELD_TYPE}}) {";
if (is_scalar && !field.IsOptional()) {
code_ +=
- " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
+ " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD}}, "
"{{BLDR_DEF_VAL}});";
} else {
- code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
+ code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD}});";
}
- code_ += " }";
+ code_ += "}";
});
// Struct initializer (all fields required);
code_ += " #[inline]";
code_ +=
" pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> "
- "{{STRUCT_NAME}}Builder<'a, 'b> {";
+ "{{STRUCT_TY}}Builder<'a, 'b> {";
code_.SetValue("NUM_FIELDS", NumToString(struct_def.fields.vec.size()));
code_ += " let start = _fbb.start_table();";
- code_ += " {{STRUCT_NAME}}Builder {";
+ code_ += " {{STRUCT_TY}}Builder {";
code_ += " fbb_: _fbb,";
code_ += " start_: start,";
code_ += " }";
@@ -1960,58 +2154,56 @@ class RustGenerator : public BaseGenerator {
code_ += " #[inline]";
code_ +=
" pub fn finish(self) -> "
- "flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {";
+ "flatbuffers::WIPOffset<{{STRUCT_TY}}<'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}}\");";
+ " self.fbb_.required(o, {{STRUCT_TY}}::{{OFFSET_NAME}},"
+ "\"{{FIELD}}\");";
});
code_ += " flatbuffers::WIPOffset::new(o.value())";
code_ += " }";
code_ += "}";
code_ += "";
- code_ += "impl std::fmt::Debug for {{STRUCT_NAME}}<'_> {";
+ code_ += "impl core::fmt::Debug for {{STRUCT_TY}}<'_> {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
- ") -> std::fmt::Result {";
- code_ += " let mut ds = f.debug_struct(\"{{STRUCT_NAME}}\");";
+ " fn fmt(&self, f: &mut core::fmt::Formatter<'_>"
+ ") -> core::fmt::Result {";
+ code_ += " let mut ds = f.debug_struct(\"{{STRUCT_TY}}\");";
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() {";
+ code_ += " match self.{{DISCRIMINANT}}() {";
ForAllUnionVariantsBesidesNone(
*field.value.type.enum_def, [&](const EnumVal &unused) {
(void)unused;
- code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
+ code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
code_ +=
- " if let Some(x) = "
- "self.{{FIELD_TYPE_FIELD_NAME}}_as_"
+ " if let Some(x) = "
+ "self.{{FIELD}}_as_"
"{{U_ELEMENT_NAME}}() {";
- code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
- code_ += " } else {";
- code_ +=
- " ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
- code_ += " }";
- code_ += " },";
+ code_ += " ds.field(\"{{FIELD}}\", &x)";
+ code_ += " } else {";
+ code_ += " ds.field(\"{{FIELD}}\", {{UNION_ERR}})";
+ code_ += " }";
+ code_ += " },";
});
- code_ += " _ => {";
- code_ += " let x: Option<()> = None;";
- code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
- code_ += " },";
- code_ += " };";
+ code_ += " _ => {";
+ code_ += " let x: Option<()> = None;";
+ code_ += " ds.field(\"{{FIELD}}\", &x)";
+ code_ += " },";
+ code_ += " };";
} else {
// Most fields.
- code_ += " ds.field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}());";
+ code_ += " ds.field(\"{{FIELD}}\", &self.{{FIELD}}());";
}
});
code_ += " ds.finish()";
@@ -2020,28 +2212,28 @@ class RustGenerator : public BaseGenerator {
}
void GenTableObject(const StructDef &table) {
- code_.SetValue("OBJECT_NAME", NativeName(table));
- code_.SetValue("STRUCT_NAME", Name(table));
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(table));
+ code_.SetValue("STRUCT_TY", namer_.Type(table));
// Generate the native object.
code_ += "#[non_exhaustive]";
code_ += "#[derive(Debug, Clone, PartialEq)]";
- code_ += "pub struct {{OBJECT_NAME}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
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_ += "pub {{FIELD}}: {{FIELD_OTY}},";
});
code_ += "}";
- code_ += "impl Default for {{OBJECT_NAME}} {";
+ code_ += "impl Default for {{STRUCT_OTY}} {";
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_ += " {{FIELD}}: " + default_value + ",";
});
code_ += " }";
code_ += " }";
@@ -2051,11 +2243,11 @@ class RustGenerator : public BaseGenerator {
// may be required, they, and therefore enums need defaults.
// Generate pack function.
- code_ += "impl {{OBJECT_NAME}} {";
+ code_ += "impl {{STRUCT_OTY}} {";
code_ += " pub fn pack<'b>(";
code_ += " &self,";
code_ += " _fbb: &mut flatbuffers::FlatBufferBuilder<'b>";
- code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'b>> {";
+ code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'b>> {";
// First we generate variables for each field and then later assemble them
// using "StructArgs" to more easily manage ownership of the builder.
ForAllObjectTableFields(table, [&](const FieldDef &field) {
@@ -2065,17 +2257,18 @@ class RustGenerator : public BaseGenerator {
case ftBool:
case ftFloat:
case ftEnumKey: {
- code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}};";
+ code_ += " let {{FIELD}} = self.{{FIELD}};";
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_.SetValue("ENUM_METHOD",
+ namer_.Method(*field.value.type.enum_def));
+ code_.SetValue("DISCRIMINANT", namer_.LegacyRustUnionTypeMethod(field));
code_ +=
- " let {{FIELD_NAME}}_type = "
- "self.{{FIELD_NAME}}.{{SNAKE_CASE_ENUM_NAME}}_type();";
- code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.pack(_fbb);";
+ " let {{DISCRIMINANT}} = "
+ "self.{{FIELD}}.{{ENUM_METHOD}}_type();";
+ code_ += " let {{FIELD}} = self.{{FIELD}}.pack(_fbb);";
return;
}
// The rest of the types require special casing around optionalness
@@ -2087,15 +2280,13 @@ class RustGenerator : public BaseGenerator {
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());";
+ code_ += " let {{FIELD}}_tmp = Some(self.{{FIELD}}.pack());";
} else {
code_ +=
- " let {{FIELD_NAME}}_tmp = self.{{FIELD_NAME}}"
+ " let {{FIELD}}_tmp = self.{{FIELD}}"
".as_ref().map(|x| x.pack());";
}
- code_ += " let {{FIELD_NAME}} = {{FIELD_NAME}}_tmp.as_ref();";
+ code_ += " let {{FIELD}} = {{FIELD}}_tmp.as_ref();";
return;
}
@@ -2123,8 +2314,8 @@ class RustGenerator : public BaseGenerator {
MapNativeTableField(
field,
- "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
- "_fbb.create_vector_of_strings(&w)");
+ "let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();"
+ "_fbb.create_vector(&w)");
return;
}
case ftVectorOfTable: {
@@ -2146,10 +2337,10 @@ class RustGenerator : public BaseGenerator {
}
}
});
- code_ += " {{STRUCT_NAME}}::create(_fbb, &{{STRUCT_NAME}}Args{";
+ code_ += " {{STRUCT_TY}}::create(_fbb, &{{STRUCT_TY}}Args{";
ForAllObjectTableFields(table, [&](const FieldDef &field) {
(void)field; // Unused.
- code_ += " {{FIELD_NAME}},";
+ code_ += " {{FIELD}},";
});
code_ += " })";
code_ += " }";
@@ -2161,23 +2352,25 @@ class RustGenerator : public BaseGenerator {
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));
+ code_.SetValue("FIELD", namer_.Field(field));
+ code_.SetValue("FIELD_OTY", ObjectFieldType(field, true));
+ code_.IncrementIdentLevel();
cb(field);
+ code_.DecrementIdentLevel();
}
}
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_ += " });";
+ code_ += " let {{FIELD}} = self.{{FIELD}}.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_ += " });";
+ code_ += " let {{FIELD}} = Some({";
+ code_ += " let x = &self.{{FIELD}};";
+ code_ += " " + expr;
+ code_ += " });";
}
}
@@ -2187,189 +2380,161 @@ class RustGenerator : public BaseGenerator {
FLATBUFFERS_ASSERT(field.key);
code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
+ code_.SetValue("REF", IsString(field.value.type) ? "" : "&");
- code_ += " #[inline]";
+ code_ += "#[inline]";
code_ +=
- " pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> "
- " bool {";
- code_ += " self.{{FIELD_NAME}}() < o.{{FIELD_NAME}}()";
- code_ += " }";
+ "pub fn key_compare_less_than(&self, o: &{{STRUCT_TY}}) -> "
+ "bool {";
+ code_ += " self.{{FIELD}}() < o.{{FIELD}}()";
+ code_ += "}";
code_ += "";
- code_ += " #[inline]";
+ 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_ += " }";
+ "pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
+ "::core::cmp::Ordering {";
+ code_ += " let key = self.{{FIELD}}();";
+ code_ += " key.cmp({{REF}}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)));
+ code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
+ code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
+ code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.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_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`";
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_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
code_ +=
- "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}(buf: &[u8]) "
- "-> Result<{{STRUCT_NAME}}, flatbuffers::InvalidFlatbuffer> {";
- code_ += " flatbuffers::root::<{{STRUCT_NAME}}>(buf)";
+ "pub fn root_as_{{STRUCT_FN}}(buf: &[u8]) "
+ "-> Result<{{STRUCT_TY}}, flatbuffers::InvalidFlatbuffer> {";
+ code_ += " flatbuffers::root::<{{STRUCT_TY}}>(buf)";
code_ += "}";
code_ += "#[inline]";
code_ += "/// Verifies that a buffer of bytes contains a size prefixed";
- code_ += "/// `{{STRUCT_NAME}}` and returns it.";
+ code_ += "/// `{{STRUCT_TY}}` 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_ += "/// `size_prefixed_root_as_{{STRUCT_FN}}_unchecked`.";
code_ +=
- "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
- "(buf: &[u8]) -> Result<{{STRUCT_NAME}}, "
+ "pub fn size_prefixed_root_as_{{STRUCT_FN}}"
+ "(buf: &[u8]) -> Result<{{STRUCT_TY}}, "
"flatbuffers::InvalidFlatbuffer> {";
- code_ += " flatbuffers::size_prefixed_root::<{{STRUCT_NAME}}>(buf)";
+ code_ += " flatbuffers::size_prefixed_root::<{{STRUCT_TY}}>(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_ += "/// contains a `{{STRUCT_TY}}` 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_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
+ code_ += "pub fn root_as_{{STRUCT_FN}}_with_opts<'b, 'o>(";
code_ += " opts: &'o flatbuffers::VerifierOptions,";
code_ += " buf: &'b [u8],";
code_ +=
- ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+ ") -> Result<{{STRUCT_TY}}<'b>, flatbuffers::InvalidFlatbuffer>"
" {";
- code_ += " flatbuffers::root_with_opts::<{{STRUCT_NAME}}<'b>>(opts, buf)";
+ code_ += " flatbuffers::root_with_opts::<{{STRUCT_TY}}<'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_ += "/// bytes contains a size prefixed `{{STRUCT_TY}}` 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_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
code_ +=
- "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts"
+ "pub fn size_prefixed_root_as_{{STRUCT_FN}}_with_opts"
"<'b, 'o>(";
code_ += " opts: &'o flatbuffers::VerifierOptions,";
code_ += " buf: &'b [u8],";
code_ +=
- ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+ ") -> Result<{{STRUCT_TY}}<'b>, flatbuffers::InvalidFlatbuffer>"
" {";
code_ +=
- " flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_NAME}}"
+ " flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_TY}}"
"<'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.";
+ "contains a {{STRUCT_TY}} and returns it.";
code_ += "/// # Safety";
code_ +=
"/// Callers must trust the given bytes do indeed contain a valid"
- " `{{STRUCT_NAME}}`.";
+ " `{{STRUCT_TY}}`.";
code_ +=
- "pub unsafe fn root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked"
- "(buf: &[u8]) -> {{STRUCT_NAME}} {";
- code_ += " flatbuffers::root_unchecked::<{{STRUCT_NAME}}>(buf)";
+ "pub unsafe fn root_as_{{STRUCT_FN}}_unchecked"
+ "(buf: &[u8]) -> {{STRUCT_TY}} {";
+ code_ += " flatbuffers::root_unchecked::<{{STRUCT_TY}}>(buf)";
code_ += "}";
code_ += "#[inline]";
code_ +=
"/// Assumes, without verification, that a buffer of bytes "
- "contains a size prefixed {{STRUCT_NAME}} and returns it.";
+ "contains a size prefixed {{STRUCT_TY}} and returns it.";
code_ += "/// # Safety";
code_ +=
"/// Callers must trust the given bytes do indeed contain a valid"
- " size prefixed `{{STRUCT_NAME}}`.";
+ " size prefixed `{{STRUCT_TY}}`.";
code_ +=
- "pub unsafe fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
- "_unchecked(buf: &[u8]) -> {{STRUCT_NAME}} {";
+ "pub unsafe fn size_prefixed_root_as_{{STRUCT_FN}}"
+ "_unchecked(buf: &[u8]) -> {{STRUCT_TY}} {";
code_ +=
- " flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}>"
+ " flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}>"
"(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_ += "pub const {{STRUCT_CONST}}_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_ += "pub fn {{STRUCT_FN}}_buffer_has_identifier\\";
code_ += "(buf: &[u8]) -> bool {";
code_ += " flatbuffers::buffer_has_identifier(buf, \\";
- code_ += "{{STRUCT_NAME_CAPS}}_IDENTIFIER, false)";
+ code_ += "{{STRUCT_CONST}}_IDENTIFIER, false)";
code_ += "}";
code_ += "";
code_ += "#[inline]";
- code_ += "pub fn {{STRUCT_NAME_SNAKECASE}}_size_prefixed\\";
+ code_ += "pub fn {{STRUCT_FN}}_size_prefixed\\";
code_ += "_buffer_has_identifier(buf: &[u8]) -> bool {";
code_ += " flatbuffers::buffer_has_identifier(buf, \\";
- code_ += "{{STRUCT_NAME_CAPS}}_IDENTIFIER, true)";
+ code_ += "{{STRUCT_CONST}}_IDENTIFIER, true)";
code_ += "}";
code_ += "";
}
if (parser_.file_extension_.length()) {
// Return the extension
- code_ += "pub const {{STRUCT_NAME_CAPS}}_EXTENSION: &str = \\";
+ code_ += "pub const {{STRUCT_CONST}}_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_ += "pub fn finish_{{STRUCT_FN}}_buffer<'a, 'b>(";
code_ += " fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
- code_ += " root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {";
+ code_ += " root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {";
if (parser_.file_identifier_.length()) {
- code_ += " fbb.finish(root, Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));";
+ code_ += " fbb.finish(root, Some({{STRUCT_CONST}}_IDENTIFIER));";
} else {
code_ += " fbb.finish(root, None);";
}
@@ -2377,14 +2542,14 @@ class RustGenerator : public BaseGenerator {
code_ += "";
code_ += "#[inline]";
code_ +=
- "pub fn finish_size_prefixed_{{STRUCT_NAME_SNAKECASE}}_buffer"
+ "pub fn finish_size_prefixed_{{STRUCT_FN}}_buffer"
"<'a, 'b>("
"fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, "
- "root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {";
+ "root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {";
if (parser_.file_identifier_.length()) {
code_ +=
" fbb.finish_size_prefixed(root, "
- "Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));";
+ "Some({{STRUCT_CONST}}_IDENTIFIER));";
} else {
code_ += " fbb.finish_size_prefixed(root, None);";
}
@@ -2421,25 +2586,30 @@ class RustGenerator : public BaseGenerator {
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_OTY", ObjectFieldType(field, false));
+ code_.SetValue("FIELD", namer_.Field(field));
code_.SetValue("FIELD_OFFSET", NumToString(offset_to_field));
code_.SetValue(
"REF",
IsStruct(field.value.type) || IsArray(field.value.type) ? "&" : "");
+ code_.IncrementIdentLevel();
cb(field);
+ code_.DecrementIdentLevel();
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) {
+ const bool is_private = parser_.opts.no_leak_private_annotations &&
+ (struct_def.attributes.Lookup("private") != nullptr);
+ code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
// 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_TY", namer_.Type(struct_def));
code_.SetValue("STRUCT_SIZE", NumToString(struct_def.bytesize));
// We represent Flatbuffers-structs in Rust-u8-arrays since the data may be
@@ -2448,25 +2618,25 @@ class RustGenerator : public BaseGenerator {
// 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_ += "// struct {{STRUCT_TY}}, 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_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}(pub [u8; {{STRUCT_SIZE}}]);";
+ code_ += "impl Default for {{STRUCT_TY}} { ";
code_ += " fn default() -> Self { ";
code_ += " Self([0; {{STRUCT_SIZE}}])";
code_ += " }";
code_ += "}";
// Debug for structs.
- code_ += "impl std::fmt::Debug for {{STRUCT_NAME}} {";
+ code_ += "impl core::fmt::Debug for {{STRUCT_TY}} {";
code_ +=
- " fn fmt(&self, f: &mut std::fmt::Formatter"
- ") -> std::fmt::Result {";
- code_ += " f.debug_struct(\"{{STRUCT_NAME}}\")";
+ " fn fmt(&self, f: &mut core::fmt::Formatter"
+ ") -> core::fmt::Result {";
+ code_ += " f.debug_struct(\"{{STRUCT_TY}}\")";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void)unused;
- code_ += " .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
+ code_ += " .field(\"{{FIELD}}\", &self.{{FIELD}}())";
});
code_ += " .finish()";
code_ += " }";
@@ -2476,44 +2646,26 @@ class RustGenerator : public BaseGenerator {
// 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_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {";
+ code_ += " type Inner = &'a {{STRUCT_TY}};";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
- code_ += " <&'a {{STRUCT_NAME}}>::follow(buf, loc)";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " <&'a {{STRUCT_TY}}>::follow(buf, loc)";
code_ += " }";
code_ += "}";
- code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_NAME}} {";
- code_ += " type Inner = &'a {{STRUCT_NAME}};";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {";
+ code_ += " type Inner = &'a {{STRUCT_TY}};";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
- code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_NAME}}>(buf, loc)";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)";
code_ += " }";
code_ += "}";
- code_ += "impl<'b> flatbuffers::Push for {{STRUCT_NAME}} {";
- code_ += " type Output = {{STRUCT_NAME}};";
+ code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {";
+ code_ += " type Output = {{STRUCT_TY}};";
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_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
+ code_ += " let src = ::core::slice::from_raw_parts(self as *const {{STRUCT_TY}} as *const u8, Self::size());";
code_ += " dst.copy_from_slice(src);";
code_ += " }";
code_ += "}";
@@ -2521,7 +2673,7 @@ class RustGenerator : public BaseGenerator {
// 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_ += "impl<'a> flatbuffers::Verifiable for {{STRUCT_TY}} {";
code_ += " #[inline]";
code_ += " fn run_verifier(";
code_ += " v: &mut flatbuffers::Verifier, pos: usize";
@@ -2530,20 +2682,51 @@ class RustGenerator : public BaseGenerator {
code_ += " v.in_buffer::<Self>(pos)";
code_ += " }";
code_ += "}";
+ code_ += "";
+
+ // Implement serde::Serialize
+ if (parser_.opts.rust_serialize) {
+ const auto numFields = struct_def.fields.vec.size();
+ code_.SetValue("NUM_FIELDS", NumToString(numFields));
+ code_ += "impl Serialize for {{STRUCT_TY}} {";
+ code_ +=
+ " fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
+ code_ += " where";
+ code_ += " S: Serializer,";
+ code_ += " {";
+ if (numFields == 0) {
+ code_ +=
+ " let s = serializer.serialize_struct(\"{{STRUCT_TY}}\", 0)?;";
+ } else {
+ code_ +=
+ " let mut s = serializer.serialize_struct(\"{{STRUCT_TY}}\", "
+ "{{NUM_FIELDS}})?;";
+ }
+ ForAllStructFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ +=
+ " s.serialize_field(\"{{FIELD}}\", "
+ "&self.{{FIELD}}())?;";
+ });
+ code_ += " s.end()";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ }
// Generate a constructor that takes all fields as arguments.
- code_ += "impl<'a> {{STRUCT_NAME}} {";
+ code_ += "impl<'a> {{STRUCT_TY}} {";
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_ += " {{FIELD}}: {{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.set_{{FIELD}}({{FIELD}});";
});
code_ += " s";
code_ += " }";
@@ -2555,12 +2738,15 @@ class RustGenerator : public BaseGenerator {
// Generate accessor methods for the struct.
ForAllStructFields(struct_def, [&](const FieldDef &field) {
- this->GenComment(field.doc_comment, " ");
+ this->GenComment(field.doc_comment);
// Getter.
if (IsStruct(field.value.type)) {
- code_ += " pub fn {{FIELD_NAME}}(&self) -> &{{FIELD_TYPE}} {";
+ code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid struct in this slot";
code_ +=
- " unsafe {"
+ " unsafe {"
" &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
" {{FIELD_TYPE}}) }";
} else if (IsArray(field.value.type)) {
@@ -2568,30 +2754,37 @@ class RustGenerator : public BaseGenerator {
NumToString(field.value.type.fixed_length));
code_.SetValue("ARRAY_ITEM", GetTypeGet(field.value.type.VectorType()));
code_ +=
- " pub fn {{FIELD_NAME}}(&'a self) -> "
+ "pub fn {{FIELD}}(&'a self) -> "
"flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
- code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
+ code_ += " unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) }";
} else {
- code_ += " pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
+ code_ += "pub fn {{FIELD}}(&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";
+ " let mut mem = core::mem::MaybeUninit::"
+ "<<{{FIELD_TYPE}} as EndianScalar>::Scalar>::uninit();";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid value in this slot";
+ code_ += " EndianScalar::from_little_endian(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}} as EndianScalar>::Scalar>(),";
+ code_ += " );";
+ code_ += " mem.assume_init()";
+ code_ += " })";
+ }
+ 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_ += "#[allow(clippy::identity_op)]"; // If FIELD_OFFSET=0.
+ code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
code_ +=
- " self.0[{{FIELD_OFFSET}}..{{FIELD_OFFSET}}+{{FIELD_SIZE}}]"
+ " 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) {
@@ -2601,36 +2794,44 @@ class RustGenerator : public BaseGenerator {
"ARRAY_ITEM_SIZE",
NumToString(InlineSize(field.value.type.VectorType())));
code_ +=
- " pub fn set_{{FIELD_NAME}}(&mut self, items: &{{FIELD_TYPE}}) "
+ "pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) "
"{";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
code_ +=
- " flatbuffers::emplace_scalar_array(&mut self.0, "
- "{{FIELD_OFFSET}}, items);";
+ " unsafe { 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_ += " }";
+ code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
+ code_ += " unsafe {";
+ code_ += " core::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";
+ code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {";
+ code_ += " let x_le = x.to_little_endian();";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid value in this slot";
+ code_ += " unsafe {";
+ code_ += " core::ptr::copy_nonoverlapping(";
+ code_ += " &x_le as *const _ as *const u8,";
+ code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
+ code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
+ code_ += " );";
+ code_ += " }";
+ }
+ code_ += "}\n";
// Generate a comparison function for this field if it is a key.
if (field.key) { GenKeyFieldMethods(field); }
@@ -2638,22 +2839,22 @@ class RustGenerator : public BaseGenerator {
// 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}} {";
+ code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
+ code_ += " pub fn unpack(&self) -> {{STRUCT_OTY}} {";
+ code_ += " {{STRUCT_OTY}} {";
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()) },";
+ " {{FIELD}}: { let {{FIELD}} = "
+ "self.{{FIELD}}(); flatbuffers::array_init(|i| "
+ "{{FIELD}}.get(i).unpack()) },";
} else {
- code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}().into(),";
+ code_ += " {{FIELD}}: self.{{FIELD}}().into(),";
}
} else {
std::string unpack = IsStruct(field.value.type) ? ".unpack()" : "";
- code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}()" + unpack + ",";
+ code_ += " {{FIELD}}: self.{{FIELD}}()" + unpack + ",";
}
});
code_ += " }";
@@ -2667,30 +2868,30 @@ class RustGenerator : public BaseGenerator {
if (parser_.opts.generate_object_based_api) {
// Struct declaration
code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
- code_ += "pub struct {{NATIVE_STRUCT_NAME}} {";
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
(void)field; // unused.
- code_ += " pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
+ code_ += "pub {{FIELD}}: {{FIELD_OTY}},";
});
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(";
+ code_ += "impl {{STRUCT_OTY}} {";
+ code_ += " pub fn pack(&self) -> {{STRUCT_TY}} {";
+ code_ += " {{STRUCT_TY}}::new(";
ForAllStructFields(struct_def, [&](const FieldDef &field) {
if (IsStruct(field.value.type)) {
- code_ += " &self.{{FIELD_NAME}}.pack(),";
+ code_ += " &self.{{FIELD}}.pack(),";
} else if (IsArray(field.value.type)) {
if (GetFullType(field.value.type) == ftArrayOfStruct) {
code_ +=
- " &flatbuffers::array_init(|i| "
- "self.{{FIELD_NAME}}[i].pack()),";
+ " &flatbuffers::array_init(|i| "
+ "self.{{FIELD}}[i].pack()),";
} else {
- code_ += " &self.{{FIELD_NAME}},";
+ code_ += " &self.{{FIELD}},";
}
} else {
- code_ += " self.{{FIELD_NAME}},";
+ code_ += " self.{{FIELD}},";
}
});
code_ += " )";
@@ -2725,9 +2926,16 @@ class RustGenerator : public BaseGenerator {
}
}
}
- code_ += indent + "use std::mem;";
- code_ += indent + "use std::cmp::Ordering;";
+ code_ += indent + "use core::mem;";
+ code_ += indent + "use core::cmp::Ordering;";
code_ += "";
+ if (parser_.opts.rust_serialize) {
+ code_ += indent + "extern crate serde;";
+ code_ +=
+ indent +
+ "use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
+ code_ += "";
+ }
code_ += indent + "extern crate flatbuffers;";
code_ += indent + "use self::flatbuffers::{EndianScalar, Follow};";
}
@@ -2766,7 +2974,7 @@ class RustGenerator : public BaseGenerator {
// 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]) + " {";
+ code_ += "pub mod " + namer_.Namespace(ns->components[j]) + " {";
// Generate local namespace imports.
GenNamespaceImports(2);
}
@@ -2774,6 +2982,9 @@ class RustGenerator : public BaseGenerator {
cur_name_space_ = ns;
}
+
+ private:
+ IdlNamer namer_;
};
} // namespace rust
@@ -2799,6 +3010,59 @@ std::string RustMakeRule(const Parser &parser, const std::string &path,
return make_rule;
}
+namespace {
+
+class RustCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateRust(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = RustMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ if (!GenerateRustModuleRootFile(parser, path)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return true; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kRust; }
+
+ std::string LanguageName() const override { return "Rust"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewRustCodeGenerator() {
+ return std::unique_ptr<RustCodeGenerator>(new RustCodeGenerator());
+}
+
} // namespace flatbuffers
// TODO(rw): Generated code should import other generated files.
diff --git a/contrib/libs/flatbuffers/src/idl_gen_rust.h b/contrib/libs/flatbuffers/src/idl_gen_rust.h
new file mode 100644
index 0000000000..ef17ed8ebf
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_rust.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_RUST_H_
+#define FLATBUFFERS_IDL_GEN_RUST_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Rust code generator.
+std::unique_ptr<CodeGenerator> NewRustCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_RUST_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_swift.cpp b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
index 3fffd39455..695f5a0d75 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "idl_gen_swift.h"
+
#include <cctype>
#include <unordered_set>
@@ -21,21 +23,133 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
namespace swift {
-inline std::string GenIndirect(const std::string &reading) {
+namespace {
+
+static Namer::Config SwiftDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kLowerCamel,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kLowerCamel,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"_",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".swift" };
+}
+
+static std::set<std::string> SwiftKeywords() {
+ return {
+ "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",
+ };
+}
+
+static 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) -> "
+static std::string GenArrayMainBody(const std::string &optional) {
+ return "{{ACCESS_TYPE}} func {{FIELDMETHOD}}(at index: Int32) -> "
"{{VALUETYPE}}" +
optional + " { ";
}
+} // namespace
+
class SwiftGenerator : public BaseGenerator {
private:
CodeWriter code_;
@@ -45,92 +159,11 @@ class SwiftGenerator : public BaseGenerator {
public:
SwiftGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", "_", "swift") {
+ : BaseGenerator(parser, path, file_name, "", "_", "swift"),
+ namer_(WithFlagOptions(SwiftDefaultConfig(), parser.opts, path),
+ SwiftKeywords()) {
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() {
@@ -140,9 +173,14 @@ class SwiftGenerator : public BaseGenerator {
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
code_ += "// swiftlint:disable all";
code_ += "// swiftformat:disable all\n";
- code_ += "import FlatBuffers\n";
- // Generate code for all the enum declarations.
+ if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
+ if (parser_.opts.swift_implementation_only)
+ code_ += "@_implementationOnly \\";
+ 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;
@@ -183,11 +221,15 @@ class SwiftGenerator : public BaseGenerator {
// Generates the reader for swift
void GenStructReader(const StructDef &struct_def) {
- auto is_private_access = struct_def.attributes.Lookup("private");
+ const bool is_private_access =
+ parser_.opts.swift_implementation_only ||
+ struct_def.attributes.Lookup("private") != nullptr;
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\\";
+ code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
+ code_ +=
+ "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct, Verifiable, "
+ "FlatbuffersInitializable\\";
if (parser_.opts.generate_object_based_api) code_ += ", NativeObject\\";
code_ += " {";
code_ += "";
@@ -201,14 +243,14 @@ class SwiftGenerator : public BaseGenerator {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const 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);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", field_var);
if (IsEnum(field.value.type)) {
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
}
@@ -216,18 +258,21 @@ class SwiftGenerator : public BaseGenerator {
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;
+ code_ += "private var _{{FIELDVAR}}: " + valueType;
+ const auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
+ const auto base_value =
+ IsStruct(field.value.type) ? (type + "()")
+ : SwiftConstant(field);
- main_constructor.push_back("_" + name + " = " + name + accessing_value);
- base_constructor.push_back("_" + name + " = " + base_value);
+ main_constructor.push_back("_" + field_var + " = " + field_var +
+ accessing_value);
+ base_constructor.push_back("_" + field_var + " = " + base_value);
if (field.padding) { GenPadding(field, &padding_id); }
- constructor += name + ": " + type;
+ constructor += field_var + ": " + type;
}
code_ += "";
+ BuildStructConstructor(struct_def);
BuildObjectConstructor(main_constructor, constructor);
BuildObjectConstructor(base_constructor, "");
@@ -236,18 +281,55 @@ class SwiftGenerator : public BaseGenerator {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const 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);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("VALUETYPE", GenType(field.value.type));
GenComment(field.doc_comment);
if (!IsEnum(field.value.type)) {
- code_ += GenReaderMainBody() + "_{{VALUENAME}} }";
+ code_ += GenReaderMainBody() + "_{{FIELDVAR}} }";
} else if (IsEnum(field.value.type)) {
code_ +=
- GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }";
+ GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{FIELDVAR}})! }";
+ }
+ }
+ code_ += "";
+ code_ +=
+ "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
+ "position: "
+ "Int, of type: T.Type) throws where T: Verifiable {";
+ Indent();
+ code_ +=
+ "try verifier.inBuffer(position: position, of: {{STRUCTNAME}}.self)";
+ Outdent();
+ code_ += "}";
+ Outdent();
+ code_ += "}\n";
+ if (parser_.opts.gen_json_coders) GenerateJSONEncodingAPIs(struct_def);
+ }
+
+ void BuildStructConstructor(const StructDef &struct_def) {
+ code_ += "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) {";
+ Indent();
+ code_ += "let {{ACCESS}} = Struct(bb: bb, position: o)";
+ 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 type = field.value.type;
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("VALUETYPE", GenType(type));
+ code_.SetValue("OFFSET", NumToString(field.value.offset));
+ if (IsScalar(type.base_type)) {
+ if (IsEnum(type))
+ code_.SetValue("VALUETYPE", GenTypeBasic(field.value.type, false));
+ code_ +=
+ "_{{FIELDVAR}} = {{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, "
+ "at: {{OFFSET}})";
+ } else {
+ code_ +=
+ "_{{FIELDVAR}} = {{VALUETYPE}}({{ACCESS}}.bb, o: "
+ "{{ACCESS}}.postion + {{OFFSET}})";
}
}
Outdent();
@@ -259,12 +341,11 @@ class SwiftGenerator : public BaseGenerator {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const 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);
+ const auto offset = NumToString(field.value.offset);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
if (IsEnum(field.value.type)) {
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
}
@@ -288,7 +369,7 @@ class SwiftGenerator : public BaseGenerator {
}
if (parser_.opts.generate_object_based_api) {
- GenerateObjectAPIExtensionHeader(NameWrappedInNameSpace(struct_def));
+ GenerateObjectAPIExtensionHeader(namer_.NamespacedType(struct_def));
code_ += "return builder.create(struct: obj)";
Outdent();
code_ += "}";
@@ -297,33 +378,6 @@ class SwiftGenerator : public BaseGenerator {
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,
@@ -332,7 +386,7 @@ class SwiftGenerator : public BaseGenerator {
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 = **it;
if (field.deprecated) continue;
const auto &field_type = field.value.type;
if (IsStruct(field.value.type)) {
@@ -340,23 +394,20 @@ class SwiftGenerator : public BaseGenerator {
*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);
+ const auto field_var = namer_.Variable(field);
+ const auto field_field = namer_.Field(field);
+ const auto type = GenType(field.value.type);
if (!is_obj_api) {
- code += nameprefix + name + ": " + type;
+ code += nameprefix + field_var + ": " + 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 += SwiftConstant(field);
}
code += ", ";
continue;
}
- code +=
- nameprefix + name + ": " + obj_api_named + object_name + "." + name;
+ code += nameprefix + field_var + ": " + obj_api_named + object_name +
+ "." + field_field;
code += ", ";
}
}
@@ -366,17 +417,21 @@ class SwiftGenerator : public BaseGenerator {
// Generates the reader for swift
void GenTable(const StructDef &struct_def) {
- auto is_private_access = struct_def.attributes.Lookup("private");
+ const bool is_private_access =
+ parser_.opts.swift_implementation_only ||
+ struct_def.attributes.Lookup("private") != nullptr;
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);
+ code_ += "";
+ GenerateVerifier(struct_def);
Outdent();
code_ += "}\n";
+ if (parser_.opts.gen_json_coders) GenerateJSONEncodingAPIs(struct_def);
}
// Generates the reader for swift
@@ -389,7 +444,7 @@ class SwiftGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (field.deprecated) { continue; }
- code_.SetValue("OFFSET_NAME", Name(field));
+ code_.SetValue("OFFSET_NAME", namer_.Variable(field));
code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
}
@@ -404,12 +459,13 @@ class SwiftGenerator : public BaseGenerator {
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("SHORT_STRUCTNAME", namer_.Type(struct_def));
+ code_.SetValue("STRUCTNAME", namer_.NamespacedType(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) code_ += ", Verifiable\\";
if (!struct_def.fixed && parser_.opts.generate_object_based_api)
code_ += ", ObjectAPIPacker\\";
code_ += " {\n";
@@ -421,19 +477,14 @@ class SwiftGenerator : public BaseGenerator {
if (!struct_def.fixed) {
if (parser_.file_identifier_.length()) {
code_.SetValue("FILENAME", parser_.file_identifier_);
+ code_ += "{{ACCESS_TYPE}} static var id: String { \"{{FILENAME}}\" } ";
code_ +=
"{{ACCESS_TYPE}} static func finish(_ fbb: inout "
"FlatBufferBuilder, end: "
"Offset, prefix: Bool = false) { fbb.finish(offset: end, "
"fileId: "
- "\"{{FILENAME}}\", addPrefix: prefix) }";
+ "{{STRUCTNAME}}.id, 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_ +=
@@ -448,7 +499,7 @@ class SwiftGenerator : public BaseGenerator {
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;
+ const auto should_generate_create = struct_def.fields.vec.size() != 0;
code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
code_ +=
@@ -508,14 +559,12 @@ class SwiftGenerator : public BaseGenerator {
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 {";
+ code_ += "{{ACCESS_TYPE}} static func " +
+ namer_.Method("sort_vector_of", struct_def) +
+ "(offsets:[Offset], "
+ "_ fbb: inout FlatBufferBuilder) -> Offset {";
Indent();
code_ += spacing + "var off = offsets";
code_ +=
@@ -526,7 +575,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += spacing + "return fbb.createVector(ofOffsets: off)";
Outdent();
code_ += "}";
- GenLookup(*key_field);
+ GenLookup(*key_field, namer_.NamespacedType(struct_def));
}
}
@@ -536,93 +585,96 @@ class SwiftGenerator : public BaseGenerator {
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 =
+ const auto field_field = namer_.Field(field);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ const auto opt_scalar =
field.IsOptional() && IsScalar(field.value.type.base_type);
- auto nullable_type = opt_scalar ? type + "?" : type;
- code_.SetValue("VALUENAME", name);
+ const auto nullable_type = opt_scalar ? type + "?" : type;
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
code_.SetValue("VALUETYPE", nullable_type);
- code_.SetValue("OFFSET", name);
- code_.SetValue("CONSTANT", field.value.constant);
+ code_.SetValue("OFFSET", namer_.Field(field));
+ code_.SetValue("CONSTANT", SwiftConstant(field));
std::string check_if_vector =
(IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf("
: "(";
- auto body = "add" + check_if_vector + name + ": ";
+ const auto body = "add" + check_if_vector + field_field + ": ";
code_ += "{{ACCESS_TYPE}} static func " + body + "\\";
- create_func_body.push_back("{{STRUCTNAME}}." + body + name + ", &fbb)");
+ create_func_body.push_back("{{STRUCTNAME}}." + body + field_field +
+ ", &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 =
+ const std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
+ const std::string optional_enum =
IsEnum(field.value.type) ? ("?" + is_enum) : "";
code_ +=
- "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\";
+ "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}}\\";
code_ += field.IsOptional() ? (optional_enum + "\\")
: (is_enum + ", def: {{CONSTANT}}\\");
code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
- auto default_value =
+ const auto default_value =
IsEnum(field.value.type)
? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
- : field.value.constant;
+ : SwiftConstant(field);
create_func_header.push_back(
- "" + name + ": " + nullable_type + " = " +
+ "" + field_field + ": " + 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";
+ std::string default_value = SwiftConstant(field);
code_.SetValue("CONSTANT", default_value);
code_.SetValue("VALUETYPE", field.IsOptional() ? "Bool?" : "Bool");
- code_ += "{{VALUETYPE}}" + builder_string +
- "fbb.add(element: {{VALUENAME}},\\";
+ code_ +=
+ "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\";
code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
create_func_header.push_back(
- name + ": " + nullable_type + " = " +
+ field_var + ": " + 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: "
+ const auto create_struct =
+ "guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };"
+ " fbb.create(struct: {{FIELDVAR}}, 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");
+ create_func_header.push_back(field_var + ": " + type +
+ (field.IsOptional() ? "? = nil" : ""));
return;
}
- auto camel_case_name =
- MakeCamel(name, false) +
+ const auto arg_label =
+ namer_.Variable(field) +
(IsVector(field.value.type) || IsArray(field.value.type)
? "VectorOffset"
: "Offset");
- create_func_header.push_back(camel_case_name + " " + name + ": " +
- "Offset = Offset()");
- auto reader_type =
+ create_func_header.push_back(arg_label + " " + field_var + ": " + "Offset" +
+ (field.IsRequired() ? "" : " = Offset()"));
+ const auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
- : "offset: {{VALUENAME}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
+ : "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
- auto vectortype = field.value.type.VectorType();
+ const 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) +
+ const auto field_name = namer_.NamespacedType(*vectortype.struct_def);
+ code_ += "{{ACCESS_TYPE}} static func " +
+ namer_.Method("start_vector_of", field_var) +
"(_ size: Int, in builder: inout "
"FlatBufferBuilder) {";
Indent();
@@ -637,23 +689,26 @@ class SwiftGenerator : public BaseGenerator {
void GenTableReader(const StructDef &struct_def) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const 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);
+ const auto offset = NumToString(field.value.offset);
+ const auto field_field = namer_.Field(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("FIELDMETHOD", namer_.Method(field));
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 + " : ";
+ code_.SetValue("OFFSET", namer_.Constant(field.name));
+ code_.SetValue("CONSTANT", SwiftConstant(field));
+ bool opt_scalar =
+ field.IsOptional() && IsScalar(field.value.type.base_type);
+ std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}";
+ std::string optional = opt_scalar ? "?" : "";
+ const 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)) {
@@ -665,19 +720,20 @@ class SwiftGenerator : public BaseGenerator {
if (IsBool(field.value.type.base_type)) {
std::string default_value =
- "0" == field.value.constant ? "false" : "true";
+ field.IsOptional() ? "nil"
+ : SwiftConstant(field);
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") + " }";
+ code_ += GenOffset() +
+ "return o == 0 ? {{CONSTANT}} : " + GenReader("VALUETYPE", "o") +
+ " }";
if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
return;
}
if (IsEnum(field.value.type)) {
- auto default_value =
+ const auto default_value =
field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
code_ += GenReaderMainBody(optional) + "\\";
@@ -688,15 +744,15 @@ class SwiftGenerator : public BaseGenerator {
return;
}
- std::string is_required = field.IsRequired() ? "!" : "?";
- auto required_reader = field.IsRequired() ? "return " : const_string;
+ const std::string is_required = field.IsRequired() ? "!" : "?";
+ const 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("FIELDVAR", namer_.Variable("mutable", field_field));
code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
code_.SetValue("CONSTANT", "nil");
code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
@@ -713,12 +769,12 @@ class SwiftGenerator : public BaseGenerator {
break;
case BASE_TYPE_STRING: {
- auto default_string = "\"" + field.value.constant + "\"";
+ const auto default_string = "\"" + SwiftConstant(field) + "\"";
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]" +
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" +
is_required +
" { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
@@ -729,7 +785,7 @@ class SwiftGenerator : public BaseGenerator {
case BASE_TYPE_UNION:
code_.SetValue("CONSTANT", "nil");
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}<T: "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: "
"FlatbuffersInitializable>(type: "
"T.Type) -> T" +
is_required + " { " + GenOffset() + required_reader +
@@ -741,20 +797,22 @@ class SwiftGenerator : public BaseGenerator {
void GenTableReaderVectorFields(const FieldDef &field) {
std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
- auto vectortype = field.value.type.VectorType();
+ const auto vectortype = field.value.type.VectorType();
code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() +
+ code_.SetValue("HAS_FIELDVAR", namer_.Variable("has", field));
+ code_ += "{{ACCESS_TYPE}} var {{HAS_FIELDVAR}}: Bool { " + GenOffset() +
+ "return o == 0 ? false : true }";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}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;
+ code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) ? "0" : "nil");
+ const auto nullable =
+ IsScalar(vectortype.base_type) && !IsEnum(vectortype) ? "" : "?";
if (vectortype.base_type != BASE_TYPE_UNION) {
code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
} else {
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}<T: FlatbuffersInitializable>(at "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at "
"index: "
"Int32, type: T.Type) -> T? { " +
GenOffset() + "\\";
@@ -773,7 +831,7 @@ class SwiftGenerator : public BaseGenerator {
"{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
code_ +=
- "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}] { return "
+ "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}] { return "
"{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) ?? [] }";
if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
return;
@@ -784,7 +842,7 @@ class SwiftGenerator : public BaseGenerator {
code_ +=
"{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
- code_.SetValue("VALUENAME", "mutable" + MakeCamel(Name(field)));
+ code_.SetValue("FIELDMETHOD", namer_.Method("mutable", field));
code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
code_ += GenArrayMainBody(nullable) + GenOffset() + const_string +
GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
@@ -819,10 +877,10 @@ class SwiftGenerator : public BaseGenerator {
code_ += GenConstructor(
"{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
"{{SIZE}})");
- auto &sd = *field.value.type.struct_def;
- auto &fields = sd.fields.vec;
+ const auto &sd = *field.value.type.struct_def;
+ const auto &fields = sd.fields.vec;
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
- auto &key_field = **kit;
+ const auto &key_field = **kit;
if (key_field.key) {
GenByKeyFunctions(key_field);
break;
@@ -831,10 +889,267 @@ class SwiftGenerator : public BaseGenerator {
}
}
+ void GenerateCodingKeys(const StructDef &struct_def) {
+ code_ += "enum CodingKeys: String, CodingKey {";
+ 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("RAWVALUENAME", field.name);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_ += "case {{FIELDVAR}} = \"{{RAWVALUENAME}}\"";
+ }
+ Outdent();
+ code_ += "}";
+ }
+
+ void GenerateEncoderUnionBody(const FieldDef &field) {
+ EnumDef &union_def = *field.value.type.enum_def;
+ const auto is_vector = field.value.type.base_type == BASE_TYPE_VECTOR ||
+ field.value.type.base_type == BASE_TYPE_ARRAY;
+ if (field.value.type.base_type == BASE_TYPE_UTYPE ||
+ (is_vector &&
+ field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
+ return;
+ if (is_vector) {
+ code_ +=
+ "var enumsEncoder = container.nestedUnkeyedContainer(forKey: "
+ ".{{FIELDVAR}}Type)";
+ code_ +=
+ "var contentEncoder = container.nestedUnkeyedContainer(forKey: "
+ ".{{FIELDVAR}})";
+ code_ += "for index in 0..<{{FIELDVAR}}Count {";
+ Indent();
+ code_ += "guard let type = {{FIELDVAR}}Type(at: index) else { continue }";
+ code_ += "try enumsEncoder.encode(type)";
+ code_ += "switch type {";
+ for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
+ code_.SetValue("VALUETYPE", type);
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_ += "case .{{KEY}}:";
+ Indent();
+ code_ += "let _v = {{FIELDVAR}}(at: index, type: {{VALUETYPE}}.self)";
+ code_ += "try contentEncoder.encode(_v)";
+ Outdent();
+ }
+ code_ += "default: break;";
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ return;
+ }
+
+ code_ += "switch {{FIELDVAR}}Type {";
+ for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
+ code_.SetValue("VALUETYPE", type);
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_ += "case .{{KEY}}:";
+ Indent();
+ code_ += "let _v = {{FIELDVAR}}(type: {{VALUETYPE}}.self)";
+ code_ += "try container.encodeIfPresent(_v, forKey: .{{FIELDVAR}})";
+ Outdent();
+ }
+ code_ += "default: break;";
+ code_ += "}";
+ }
+
+ void GenerateEncoderBody(const StructDef &struct_def) {
+ code_ += "var container = encoder.container(keyedBy: CodingKeys.self)";
+ 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 type = field.value.type;
+
+ const auto is_non_union_vector =
+ (field.value.type.base_type == BASE_TYPE_ARRAY ||
+ field.value.type.base_type == BASE_TYPE_VECTOR) &&
+ field.value.type.VectorType().base_type != BASE_TYPE_UTYPE;
+
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("CONSTANT", SwiftConstant(field));
+ bool should_indent = true;
+ if (is_non_union_vector) {
+ code_ += "if {{FIELDVAR}}Count > 0 {";
+ } else if (IsEnum(type) && !field.IsOptional()) {
+ code_.SetValue("CONSTANT", GenEnumDefaultValue(field));
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
+ } else if (IsFloat(type.base_type) && StringIsFlatbufferNan(field.value.constant)) {
+ code_ += "if !{{FIELDVAR}}.isNaN {";
+ } else if (IsScalar(type.base_type) && !IsEnum(type) &&
+ !IsBool(type.base_type) && !field.IsOptional()) {
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
+ } else if (IsBool(type.base_type) && !field.IsOptional()) {
+ code_.SetValue("CONSTANT", SwiftConstant(field));
+ code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
+ } else {
+ should_indent = false;
+ }
+ if (should_indent) Indent();
+
+ if (IsUnion(type) && !IsEnum(type)) {
+ GenerateEncoderUnionBody(field);
+ } else if (is_non_union_vector &&
+ (!IsScalar(type.VectorType().base_type) ||
+ IsEnum(type.VectorType()))) {
+ code_ +=
+ "var contentEncoder = container.nestedUnkeyedContainer(forKey: "
+ ".{{FIELDVAR}})";
+ code_ += "for index in 0..<{{FIELDVAR}}Count {";
+ Indent();
+ code_ += "guard let type = {{FIELDVAR}}(at: index) else { continue }";
+ code_ += "try contentEncoder.encode(type)";
+ Outdent();
+ code_ += "}";
+ } else {
+ code_ +=
+ "try container.encodeIfPresent({{FIELDVAR}}, forKey: "
+ ".{{FIELDVAR}})";
+ }
+ if (should_indent) Outdent();
+
+ if (is_non_union_vector ||
+ (IsScalar(type.base_type) && !field.IsOptional())) {
+ code_ += "}";
+ }
+ }
+ }
+
+ void GenerateJSONEncodingAPIs(const StructDef &struct_def) {
+ code_ += "extension {{STRUCTNAME}}: Encodable {";
+ Indent();
+ code_ += "";
+ if (struct_def.fields.vec.empty() == false) GenerateCodingKeys(struct_def);
+
+ code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
+ Indent();
+ if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
+ Outdent();
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ code_ += "";
+ }
+
+ void GenerateVerifier(const StructDef &struct_def) {
+ code_ +=
+ "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
+ "position: "
+ "Int, of type: T.Type) throws where T: Verifiable {";
+ Indent();
+ code_ += "var _v = try verifier.visitTable(at: position)";
+ 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 offset = NumToString(field.value.offset);
+
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
+ code_.SetValue("VALUETYPE", GenerateVerifierType(field));
+ code_.SetValue("OFFSET", namer_.Field(field));
+ code_.SetValue("ISREQUIRED", field.IsRequired() ? "true" : "false");
+
+ if (IsUnion(field.value.type)) {
+ GenerateUnionTypeVerifier(field);
+ continue;
+ }
+
+ code_ +=
+ "try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
+ "\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: "
+ "{{VALUETYPE}}.self)";
+ }
+ code_ += "_v.finish()";
+ Outdent();
+ code_ += "}";
+ }
+
+ void GenerateUnionTypeVerifier(const FieldDef &field) {
+ const auto is_vector =
+ IsVector(field.value.type) || IsArray(field.value.type);
+ if (field.value.type.base_type == BASE_TYPE_UTYPE ||
+ (is_vector &&
+ field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
+ return;
+ EnumDef &union_def = *field.value.type.enum_def;
+ code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def));
+ code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
+ code_ +=
+ "try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
+ "unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
+ "\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: "
+ "{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
+ Indent();
+ code_ += "switch key {";
+ for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ const auto type = GenType(ev.union_type);
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
+ code_.SetValue("VALUETYPE", type);
+ code_ += "case .{{KEY}}:";
+ Indent();
+ if (ev.union_type.base_type == BASE_TYPE_NONE) {
+ code_ += "break // NOTE - SWIFT doesnt support none";
+ } else if (ev.union_type.base_type == BASE_TYPE_STRING) {
+ code_ +=
+ "try ForwardOffset<String>.verify(&verifier, at: pos, of: "
+ "String.self)";
+ } else {
+ code_.SetValue("MAINTYPE", ev.union_type.struct_def->fixed
+ ? type
+ : "ForwardOffset<" + type + ">");
+ code_ +=
+ "try {{MAINTYPE}}.verify(&verifier, at: pos, of: "
+ "{{VALUETYPE}}.self)";
+ }
+ Outdent();
+ }
+ code_ += "}";
+ Outdent();
+ code_ += "})";
+ }
+
+ std::string GenerateVerifierType(const FieldDef &field) {
+ const auto type = field.value.type;
+ const auto is_vector = IsVector(type) || IsArray(type);
+
+ if (is_vector) {
+ const auto vector_type = field.value.type.VectorType();
+ return "ForwardOffset<Vector<" +
+ GenerateNestedVerifierTypes(vector_type) + ", " +
+ GenType(vector_type) + ">>";
+ }
+
+ return GenerateNestedVerifierTypes(field.value.type);
+ }
+
+ std::string GenerateNestedVerifierTypes(const Type &type) {
+ const auto string_type = GenType(type);
+
+ if (IsScalar(type.base_type)) { return string_type; }
+
+ if (IsString(type)) { return "ForwardOffset<" + string_type + ">"; }
+
+ if (type.struct_def && type.struct_def->fixed) { return string_type; }
+
+ return "ForwardOffset<" + string_type + ">";
+ }
+
void GenByKeyFunctions(const FieldDef &key_field) {
code_.SetValue("TYPE", GenType(key_field.value.type));
code_ +=
- "{{ACCESS_TYPE}} func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
+ "{{ACCESS_TYPE}} func {{FIELDVAR}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
"{ \\";
code_ += GenOffset() +
"return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
@@ -843,14 +1158,26 @@ class SwiftGenerator : public BaseGenerator {
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
- auto is_private_access = enum_def.attributes.Lookup("private");
+ const bool is_private_access = parser_.opts.swift_implementation_only ||
+ enum_def.attributes.Lookup("private") != nullptr;
+ code_.SetValue("ENUM_TYPE",
+ enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
- code_.SetValue("ENUM_NAME", NameWrappedInNameSpace(enum_def));
+ code_.SetValue("ENUM_NAME", namer_.NamespacedType(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 {";
+ code_ +=
+ "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, {{ENUM_TYPE}} {";
Indent();
code_ += "{{ACCESS_TYPE}} typealias T = {{BASE_TYPE}}";
+ if (enum_def.is_union) {
+ code_ += "";
+ code_ += "{{ACCESS_TYPE}} init?(value: T) {";
+ Indent();
+ code_ += "self.init(rawValue: value)";
+ Outdent();
+ code_ += "}\n";
+ }
code_ +=
"{{ACCESS_TYPE}} static var byteSize: Int { return "
"MemoryLayout<{{BASE_TYPE}}>.size "
@@ -859,17 +1186,20 @@ class SwiftGenerator : public BaseGenerator {
"{{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("KEY", namer_.LegacySwiftVariant(ev));
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");
+ code_ += "";
+ AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MaxValue()),
+ "max");
+ AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MinValue()),
+ "min");
Outdent();
code_ += "}\n";
+ if (parser_.opts.gen_json_coders) EnumEncoder(enum_def);
+ code_ += "";
if (parser_.opts.generate_object_based_api && enum_def.is_union) {
code_ += "{{ACCESS_TYPE}} struct {{ENUM_NAME}}Union {";
Indent();
@@ -894,20 +1224,40 @@ class SwiftGenerator : public BaseGenerator {
}
}
+ void EnumEncoder(const EnumDef &enum_def) {
+ code_ += "extension {{ENUM_NAME}}: Encodable {";
+ Indent();
+ code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
+ Indent();
+ code_ += "var container = encoder.singleValueContainer()";
+ code_ += "switch self {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
+ code_.SetValue("RAWKEY", ev.name);
+ code_ += "case .{{KEY}}: try container.encode(\"{{RAWKEY}}\")";
+ }
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ }
+
// MARK: - Object API
- void GenerateObjectAPIExtensionHeader(std::string name) {
+ void GenerateObjectAPIExtensionHeader(std::string type_name) {
code_ += "\n";
- code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + name + " {";
+ code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + type_name + " {";
Indent();
- code_ += "return " + name + "(&self)";
+ code_ += "return " + type_name + "(&self)";
Outdent();
code_ += "}";
code_ +=
"{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
"obj: "
"inout " +
- name + "?) -> Offset {";
+ type_name + "?) -> Offset {";
Indent();
code_ += "guard var obj = obj else { return Offset() }";
code_ += "return pack(&builder, obj: &obj)";
@@ -918,7 +1268,7 @@ class SwiftGenerator : public BaseGenerator {
"{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
"obj: "
"inout " +
- name + ") -> Offset {";
+ type_name + ") -> Offset {";
Indent();
}
@@ -928,40 +1278,39 @@ class SwiftGenerator : public BaseGenerator {
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
- auto &field = **it;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = GenType(field.value.type);
- code_.SetValue("VALUENAME", name);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", namer_.Variable(field));
if (IsStruct(field.value.type)) {
- code_ += "var _v{{VALUENAME}} = _t.{{VALUENAME}}";
- code_ += "_{{VALUENAME}} = _v{{VALUENAME}}.unpack()";
+ code_ += "var _v{{FIELDVAR}} = _t.{{FIELDVAR}}";
+ code_ += "_{{FIELDVAR}} = _v{{FIELDVAR}}.unpack()";
continue;
}
std::string is_enum = IsEnum(field.value.type) ? ".value" : "";
- code_ += "_{{VALUENAME}} = _t.{{VALUENAME}}" + is_enum;
+ code_ += "_{{FIELDVAR}} = _t.{{FIELDVAR}}" + is_enum;
}
Outdent();
code_ += "}\n";
}
void GenObjectAPI(const StructDef &struct_def) {
- code_ += "{{ACCESS_TYPE}} class " + ObjectAPIName("{{STRUCTNAME}}") +
- ": NativeObject {\n";
+ code_ += "{{ACCESS_TYPE}} class " +
+ namer_.NamespacedObjectType(struct_def) + ": 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;
+ const 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));
+ "_ _t: inout " + namer_.NamespacedType(struct_def));
BuildObjectConstructor(base_constructor);
if (!struct_def.fixed)
code_ +=
@@ -973,35 +1322,37 @@ class SwiftGenerator : public BaseGenerator {
}
void GenerateObjectAPITableExtension(const StructDef &struct_def) {
- GenerateObjectAPIExtensionHeader(ObjectAPIName("{{STRUCTNAME}}"));
+ GenerateObjectAPIExtensionHeader(namer_.NamespacedObjectType(struct_def));
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;
+ const auto &field = **it;
if (field.deprecated) continue;
- auto name = Name(field);
- auto type = GenType(field.value.type);
+ const auto field_var = namer_.Variable(field);
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const 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 + ": ";
+ std::string body = "add" + check_if_vector + field_method + ": ";
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 +
+ GenerateVectorObjectAPITableExtension(field);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
break;
}
case BASE_TYPE_UNION: {
- code_ += "let __" + name + " = obj." + name +
+ code_ += "let __" + field_var + " = obj." + field_var +
"?.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 +
+ unpack_body.push_back("if let o = obj." + field_var + "?.type {");
+ unpack_body.push_back(" {{STRUCTNAME}}.add(" + field_var +
+ "Type: o" + builder);
+ unpack_body.push_back(" {{STRUCTNAME}}." + body + "__" + field_var +
builder);
unpack_body.push_back("}\n");
break;
@@ -1015,31 +1366,31 @@ class SwiftGenerator : public BaseGenerator {
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);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
+ field_field + builder);
} else {
- code_ += "let __" + name + " = " + type +
- ".pack(&builder, obj: &obj." + name + ")";
- unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ code_ += "let __" + field_var + " = " + type +
+ ".pack(&builder, obj: &obj." + field_field + ")";
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
}
break;
}
case BASE_TYPE_STRING: {
- unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
builder);
if (field.IsRequired()) {
- code_ +=
- "let __" + name + " = builder.create(string: obj." + name + ")";
+ code_ += "let __" + field_var + " = builder.create(string: obj." +
+ field_field + ")";
} else {
- BuildingOptionalObjects(name, "builder.create(string: s)");
+ BuildingOptionalObjects(field_field, "builder.create(string: s)");
}
break;
}
case BASE_TYPE_UTYPE: break;
default:
- unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
- builder);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
+ field_field + builder);
}
}
code_ += "let __root = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&builder)";
@@ -1052,78 +1403,79 @@ class SwiftGenerator : public BaseGenerator {
code_ += "}";
}
- void GenerateVectorObjectAPITableExtension(const FieldDef &field,
- const std::string &name,
- const std::string &type) {
- auto vectortype = field.value.type.VectorType();
+ void GenerateVectorObjectAPITableExtension(const FieldDef &field_def) {
+ const Type &field_type = field_def.value.type;
+ const auto type = GenType(field_type);
+ const auto var = namer_.Variable(field_def);
+ const auto field = namer_.Field(field_def);
+
+ const auto vectortype = field_type.VectorType();
switch (vectortype.base_type) {
case BASE_TYPE_UNION: {
- code_ += "var __" + name + "__: [Offset] = []";
- code_ += "for i in obj." + name + " {";
+ code_ += "var __" + var + "__: [Offset] = []";
+ code_ += "for i in obj." + var + " {";
Indent();
code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
- code_ += "__" + name + "__.append(off)";
+ code_ += "__" + var + "__.append(off)";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
- name + "__)";
- code_ += "let __" + name + "Type = builder.createVector(obj." + name +
+ code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
+ var + "__)";
+ code_ += "let __" + var + "Type = builder.createVector(obj." + field +
".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 + " {";
+ if (field_type.struct_def && !field_type.struct_def->fixed) {
+ code_ += "var __" + var + "__: [Offset] = []";
+ code_ += "for var i in obj." + var + " {";
Indent();
code_ +=
- "__" + name + "__.append(" + type + ".pack(&builder, obj: &i))";
+ "__" + var + "__.append(" + type + ".pack(&builder, obj: &i))";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
- name + "__)";
+ code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
+ var + "__)";
} else {
- code_ += "{{STRUCTNAME}}.startVectorOf" + MakeCamel(name, true) +
- "(obj." + name + ".count, in: &builder)";
+ code_ += "{{STRUCTNAME}}." + namer_.Method("start_vector_of", var) +
+ "(obj." + field + ".count, in: &builder)";
std::string code;
- GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "_o",
- true);
+ GenerateStructArgs(*field_type.struct_def, &code, "", "", "_o", true);
code = code.substr(0, code.size() - 2);
- code_ += "for i in obj." + name + " {";
+ code_ += "for i in obj." + field + " {";
Indent();
code_ += "guard let _o = i else { continue }";
code_ += "builder.create(struct: _o)";
Outdent();
code_ += "}";
- code_ += "let __" + name + " = builder.endVector(len: obj." + name +
+ code_ += "let __" + var + " = builder.endVector(len: obj." + field +
".count)";
}
break;
}
case BASE_TYPE_STRING: {
- code_ += "let __" + name + " = builder.createVector(ofStrings: obj." +
- name + ".compactMap({ $0 }) )";
+ code_ += "let __" + var + " = builder.createVector(ofStrings: obj." +
+ var + ".compactMap({ $0 }) )";
break;
}
default: {
- code_ += "let __" + name + " = builder.createVector(obj." + name + ")";
+ code_ += "let __" + var + " = builder.createVector(obj." + field + ")";
break;
}
}
}
- void BuildingOptionalObjects(const std::string &name,
+ void BuildingOptionalObjects(const std::string &var,
const std::string &body_front) {
- code_ += "let __" + name + ": Offset";
- code_ += "if let s = obj." + name + " {";
+ code_ += "let __" + var + ": Offset";
+ code_ += "if let s = obj." + var + " {";
Indent();
- code_ += "__" + name + " = " + body_front;
+ code_ += "__" + var + " = " + body_front;
Outdent();
code_ += "} else {";
Indent();
- code_ += "__" + name + " = Offset()";
+ code_ += "__" + var + " = Offset()";
Outdent();
code_ += "}";
code_ += "";
@@ -1143,120 +1495,123 @@ class SwiftGenerator : public BaseGenerator {
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);
+ const auto field_field = namer_.Field(field);
+ const auto field_var = namer_.Variable(field);
+ const auto type = GenType(field.value.type);
+ code_.SetValue("FIELDVAR", field_field);
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 =
+ const auto objtype = GenType(field.value.type, true);
+ code_.SetValue("VALUETYPE", objtype);
+ const 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 + "()");
+ "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + question_mark;
+ base_constructor.push_back("" + field_var + " = " + objtype + "()");
if (field.value.type.struct_def->fixed) {
- buffer_constructor.push_back("" + name + " = _t." + name);
+ buffer_constructor.push_back("" + field_var + " = _t." + field_field);
} else {
- buffer_constructor.push_back("var __" + name + " = _t." + name);
+ buffer_constructor.push_back("var __" + field_var + " = _t." +
+ field_field);
buffer_constructor.push_back(
- "" + name + " = __" + name +
+ "" + field_var + " = __" + field_var +
(field.IsRequired() ? "!" : question_mark) + ".unpack()");
}
break;
}
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
- BuildObjectAPIConstructorBodyVectors(field, name, buffer_constructor,
+ BuildObjectAPIConstructorBodyVectors(field, buffer_constructor,
base_constructor, " ");
break;
}
case BASE_TYPE_STRING: {
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required;
- buffer_constructor.push_back(name + " = _t." + name);
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: String" + is_required;
+ buffer_constructor.push_back(field_var + " = _t." + field_field);
if (field.IsRequired()) {
std::string default_value =
- field.IsDefault() ? field.value.constant : "";
- base_constructor.push_back(name + " = \"" + default_value + "\"");
+ field.IsDefault() ? SwiftConstant(field) : "";
+ base_constructor.push_back(field_var + " = \"" + default_value +
+ "\"");
break;
}
if (field.IsDefault() && !field.IsRequired()) {
- std::string value = field.IsDefault() ? field.value.constant : "nil";
- base_constructor.push_back(name + " = \"" + value + "\"");
+ std::string value = field.IsDefault() ? SwiftConstant(field) : "nil";
+ base_constructor.push_back(field_var + " = \"" + value + "\"");
}
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
- BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
buffer_constructor);
break;
}
default: {
- buffer_constructor.push_back(name + " = _t." + name);
+ buffer_constructor.push_back(field_var + " = _t." + field_field);
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;
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + nullable;
if (!field.IsOptional())
- base_constructor.push_back(name + " = " + field.value.constant);
+ base_constructor.push_back(field_var + " = " +
+ SwiftConstant(field));
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);
+ const auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : SwiftConstant(field);
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}";
+ base_constructor.push_back(field_var + " = " + 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";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: Bool" + nullable;
if (!field.IsOptional())
- base_constructor.push_back(name + " = " + default_value);
+ base_constructor.push_back(field_var + " = " + SwiftConstant(field));
}
}
}
}
void BuildObjectAPIConstructorBodyVectors(
- const FieldDef &field, const std::string &name,
- std::vector<std::string> &buffer_constructor,
+ const FieldDef &field, std::vector<std::string> &buffer_constructor,
std::vector<std::string> &base_constructor,
const std::string &indentation) {
- auto vectortype = field.value.type.VectorType();
+ const auto vectortype = field.value.type.VectorType();
+ const auto field_var = namer_.Field(field);
+ const auto field_field = namer_.Field(field);
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 + " = []");
+ buffer_constructor.push_back(field_var + " = []");
+ buffer_constructor.push_back("for index in 0..<_t." + field_field +
+ "Count {");
+ base_constructor.push_back(field_var + " = []");
}
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
code_.SetValue("VALUETYPE", GenType(vectortype, true));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}?]";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}?]";
if (!vectortype.struct_def->fixed) {
- buffer_constructor.push_back(indentation + "var __v_ = _t." + name +
- "(at: index)");
- buffer_constructor.push_back(indentation + name +
+ buffer_constructor.push_back(indentation + "var __v_ = _t." +
+ field_field + "(at: index)");
+ buffer_constructor.push_back(indentation + field_var +
".append(__v_?.unpack())");
} else {
- buffer_constructor.push_back(indentation + name + ".append(_t." +
- name + "(at: index))");
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_var + "(at: index))");
}
break;
}
@@ -1265,7 +1620,7 @@ class SwiftGenerator : public BaseGenerator {
break;
}
case BASE_TYPE_UNION: {
- BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
buffer_constructor, indentation, true);
break;
}
@@ -1274,18 +1629,18 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue(
"VALUETYPE",
(IsString(vectortype) ? "String?" : GenType(vectortype)));
- code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}]";
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{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)!)");
+ const auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : SwiftConstant(field);
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_field + "(at: index)!)");
break;
}
- buffer_constructor.push_back(indentation + name + ".append(_t." + name +
- "(at: index))");
+ buffer_constructor.push_back(indentation + field_var + ".append(_t." +
+ field_field + "(at: index))");
break;
}
}
@@ -1293,19 +1648,17 @@ class SwiftGenerator : public BaseGenerator {
buffer_constructor.push_back("}");
}
- void BuildUnionEnumSwitchCaseWritter(const EnumDef &ev) {
- auto field_name = Name(ev);
- code_.SetValue("VALUETYPE", field_name);
+ void BuildUnionEnumSwitchCaseWritter(const EnumDef &ed) {
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 + ":";
+ for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
+ const auto ev = **it;
+ const auto variant = namer_.LegacySwiftVariant(ev);
+ const auto type = GenType(ev.union_type);
+ const auto is_struct = IsStruct(ev.union_type) ? type + Mutable() : type;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_ += "case ." + variant + ":";
Indent();
- code_ += "var __obj = value as? " + GenType(field.union_type, true);
+ code_ += "var __obj = value as? " + GenType(ev.union_type, true);
code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)";
Outdent();
}
@@ -1313,34 +1666,34 @@ class SwiftGenerator : public BaseGenerator {
code_ += "}";
}
- void BuildUnionEnumSwitchCase(const EnumDef &ev, const std::string &name,
+ void BuildUnionEnumSwitchCase(const EnumDef &ed, const std::string &field,
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}}: \\";
+ const auto ns_type = namer_.NamespacedType(ed);
+ code_.SetValue("VALUETYPE", ns_type);
+ code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: \\";
code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
- auto vector_reader = is_vector ? "(at: index" : "";
- buffer_constructor.push_back(indentation + "switch _t." + name + "Type" +
+ const auto vector_reader = is_vector ? "(at: index" : "";
+ buffer_constructor.push_back(indentation + "switch _t." + field + "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 + ":");
+ for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
+ const auto ev = **it;
+ const auto variant = namer_.LegacySwiftVariant(ev);
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ const auto type = IsStruct(ev.union_type)
+ ? GenType(ev.union_type) + Mutable()
+ : GenType(ev.union_type);
+ buffer_constructor.push_back(indentation + "case ." + variant + ":");
buffer_constructor.push_back(
- indentation + " var _v = _t." + name + (is_vector ? "" : "(") +
+ indentation + " var _v = _t." + field + (is_vector ? "" : "(") +
vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)");
- auto constructor =
- field_name + "Union(_v?.unpack(), type: ." + ev_name + ")";
+ const auto constructor =
+ ns_type + "Union(_v?.unpack(), type: ." + variant + ")";
buffer_constructor.push_back(
- indentation + " " + name +
+ indentation + " " + field +
(is_vector ? ".append(" + constructor + ")" : " = " + constructor));
}
buffer_constructor.push_back(indentation + "default: break");
@@ -1348,13 +1701,14 @@ class SwiftGenerator : public BaseGenerator {
}
void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
- auto current_value = str;
+ const 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) {
+ void GenLookup(const FieldDef &key_field, const std::string &struct_type) {
+ code_.SetValue("STRUCTTYPE", struct_type);
code_.SetValue("OFFSET", NumToString(key_field.value.offset));
std::string offset_reader =
"Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
@@ -1364,7 +1718,7 @@ class SwiftGenerator : public BaseGenerator {
code_ +=
"fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
"fbb: "
- "ByteBuffer) -> {{VALUENAME}}? {";
+ "ByteBuffer) -> {{STRUCTTYPE}}? {";
Indent();
if (IsString(key_field.value.type))
code_ += "let key = key.utf8.map { $0 }";
@@ -1394,7 +1748,7 @@ class SwiftGenerator : public BaseGenerator {
Outdent();
code_ += "} else {";
Indent();
- code_ += "return {{VALUENAME}}(fbb, o: tableOffset)";
+ code_ += "return {{STRUCTTYPE}}(fbb, o: tableOffset)";
Outdent();
code_ += "}";
Outdent();
@@ -1408,7 +1762,7 @@ class SwiftGenerator : public BaseGenerator {
if (field.padding) {
for (int i = 0; i < 4; i++) {
if (static_cast<int>(field.padding) & (1 << i)) {
- auto bits = (1 << i) * 8;
+ const auto bits = (1 << i) * 8;
code_ += "private let padding" + NumToString((*id)++) + "__: UInt" +
NumToString(bits) + " = 0";
}
@@ -1430,8 +1784,7 @@ class SwiftGenerator : public BaseGenerator {
}
std::string GenReaderMainBody(const std::string &optional = "") {
- return "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + optional +
- " { ";
+ return "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + optional + " { ";
}
std::string GenReader(const std::string &type,
@@ -1445,52 +1798,58 @@ class SwiftGenerator : public BaseGenerator {
std::string GenMutate(const std::string &offset,
const std::string &get_offset, bool isRaw = false) {
- return "@discardableResult {{ACCESS_TYPE}} func mutate({{VALUENAME}}: "
+ return "@discardableResult {{ACCESS_TYPE}} func mutate({{FIELDVAR}}: "
"{{VALUETYPE}}) -> Bool {" +
- get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
+ get_offset + " return {{ACCESS}}.mutate({{FIELDVAR}}" +
(isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
}
std::string GenMutateArray() {
- return "{{ACCESS_TYPE}} func mutate({{VALUENAME}}: {{VALUETYPE}}, at "
- "index: "
- "Int32) -> Bool { " +
+ return "{{ACCESS_TYPE}} func mutate({{FIELDVAR}}: {{VALUETYPE}}, at "
+ "index: Int32) -> Bool { " +
GenOffset() +
- "return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
+ "return {{ACCESS}}.directMutate({{FIELDVAR}}, index: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
}
std::string GenEnumDefaultValue(const FieldDef &field) {
- auto &value = field.value;
+ const auto &value = field.value;
FLATBUFFERS_ASSERT(value.type.enum_def);
- auto &enum_def = *value.type.enum_def;
+ const 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;
+ const auto enum_val = enum_def.FindByValue(constant);
if (enum_val) {
- name = Name(*enum_val);
+ return "." + namer_.LegacySwiftVariant(*enum_val);
} else {
const auto &ev = **enum_def.Vals().begin();
- name = Name(ev);
+ return "." + namer_.LegacySwiftVariant(ev);
}
- return "." + name;
}
+ std::string SwiftConstant(const FieldDef& field) {
+ const auto default_value =
+ StringIsFlatbufferNan(field.value.constant) ? ".nan" :
+ StringIsFlatbufferPositiveInfinity(field.value.constant) ? ".infinity" :
+ StringIsFlatbufferNegativeInfinity(field.value.constant) ? "-.infinity" :
+ IsBool(field.value.type.base_type) ? ("0" == field.value.constant ? "false" : "true") :
+ field.value.constant;
+ return default_value;
+ }
+
std::string GenEnumConstructor(const std::string &at) {
return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
}
std::string ValidateFunc() {
- return "static func validateVersion() { FlatBuffersVersion_2_0_0() }";
+ return "static func validateVersion() { FlatBuffersVersion_23_5_9() }";
}
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));
+ return IsScalar(type.base_type) ? GenTypeBasic(type)
+ : IsArray(type) ? GenType(type.VectorType())
+ : GenTypePointer(type, should_consider_suffix);
}
std::string GenTypePointer(const Type &type,
@@ -1499,12 +1858,11 @@ class SwiftGenerator : public BaseGenerator {
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_)));
+ const auto &sd = *type.struct_def;
+ if (should_consider_suffix && !sd.fixed) {
+ return namer_.NamespacedObjectType(sd);
}
- return WrapInNameSpace(struct_.defined_namespace, Name(struct_));
+ return namer_.NamespacedType(sd);
}
case BASE_TYPE_UNION:
default: return "FlatbuffersInitializable";
@@ -1515,56 +1873,30 @@ class SwiftGenerator : public BaseGenerator {
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) \
+ 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.enum_def) return namer_.NamespacedType(*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));
- }
+ IdlNamer namer_;
};
} // namespace swift
bool GenerateSwift(const Parser &parser, const std::string &path,
@@ -1572,4 +1904,60 @@ bool GenerateSwift(const Parser &parser, const std::string &path,
swift::SwiftGenerator generator(parser, path, file_name);
return generator.generate();
}
+
+namespace {
+
+class SwiftCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateSwift(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateSwiftGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ (void)output;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kSwift; }
+
+ std::string LanguageName() const override { return "Swift"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewSwiftCodeGenerator() {
+ return std::unique_ptr<SwiftCodeGenerator>(new SwiftCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_swift.h b/contrib/libs/flatbuffers/src/idl_gen_swift.h
new file mode 100644
index 0000000000..4fd8977d40
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_swift.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_SWIFT_H_
+#define FLATBUFFERS_IDL_GEN_SWIFT_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Cpp code generator.
+std::unique_ptr<CodeGenerator> NewSwiftCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_SWIFT_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_text.cpp b/contrib/libs/flatbuffers/src/idl_gen_text.cpp
index 903c41ecdb..59f6844413 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_text.cpp
@@ -15,7 +15,12 @@
*/
// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_text.h"
+#include <algorithm>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/code_generator.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h"
#include "flatbuffers/idl.h"
@@ -50,10 +55,10 @@ struct JsonPrinter {
// 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*/) {
+ void PrintScalar(T val, const Type &type, int /*indent*/) {
if (IsBool(type.base_type)) {
text += val != 0 ? "true" : "false";
- return true; // done
+ return; // done
}
if (opts.output_enum_identifiers && type.enum_def) {
@@ -62,7 +67,7 @@ struct JsonPrinter {
text += '\"';
text += ev->name;
text += '\"';
- return true; // done
+ return; // done
} else if (val && enum_def.attributes.Lookup("bit_flags")) {
const auto entry_len = text.length();
const auto u64 = static_cast<uint64_t>(val);
@@ -80,7 +85,7 @@ struct JsonPrinter {
// Don't slice if (u64 != mask)
if (mask && (u64 == mask)) {
text[text.length() - 1] = '\"';
- return true; // done
+ return; // done
}
text.resize(entry_len); // restore
}
@@ -88,7 +93,7 @@ struct JsonPrinter {
}
text += NumToString(val);
- return true;
+ return;
}
void AddComma() {
@@ -97,36 +102,36 @@ struct JsonPrinter {
// 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,
+ template<typename Container, typename SizeT = typename Container::size_type>
+ const char *PrintContainer(PrintScalarTag, const Container &c, SizeT 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++) {
+ for (SizeT i = 0; i < size; i++) {
if (i) {
AddComma();
AddNewLine();
}
AddIndent(elem_indent);
- if (!PrintScalar(c[i], type, elem_indent)) { return false; }
+ PrintScalar(c[i], type, elem_indent);
}
AddNewLine();
AddIndent(indent);
text += ']';
- return true;
+ return nullptr;
}
// 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,
+ template<typename Container, typename SizeT = typename Container::size_type>
+ const char *PrintContainer(PrintPointerTag, const Container &c, SizeT 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++) {
+ for (SizeT i = 0; i < size; i++) {
if (i) {
AddComma();
AddNewLine();
@@ -135,21 +140,20 @@ struct JsonPrinter {
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;
- }
+ auto err = PrintOffset(ptr, type, elem_indent, prev_val,
+ static_cast<soffset_t>(i));
+ if (err) return err;
}
AddNewLine();
AddIndent(indent);
text += ']';
- return true;
+ return nullptr;
}
- template<typename T>
- bool PrintVector(const void *val, const Type &type, int indent,
+ template<typename T, typename SizeT = uoffset_t>
+ const char *PrintVector(const void *val, const Type &type, int indent,
const uint8_t *prev_val) {
- typedef Vector<T> Container;
+ typedef Vector<T, SizeT> 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,
@@ -158,14 +162,16 @@ struct JsonPrinter {
// 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) {
+ const char *PrintArray(const void *val, uint16_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 char *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: {
@@ -182,7 +188,7 @@ struct JsonPrinter {
if (enum_val) {
return PrintOffset(val, enum_val->union_type, indent, nullptr, -1);
} else {
- return false;
+ return "unknown enum value";
}
}
case BASE_TYPE_STRUCT:
@@ -190,8 +196,9 @@ struct JsonPrinter {
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);
+ bool ok = EscapeString(s->c_str(), s->size(), &text, opts.allow_non_utf8,
+ opts.natural_utf8);
+ return ok ? nullptr : "string contains non-utf8 bytes";
}
case BASE_TYPE_VECTOR: {
const auto vec_type = type.VectorType();
@@ -199,17 +206,15 @@ struct JsonPrinter {
// 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;
+ case BASE_TYPE_ ## ENUM: { \
+ auto err = PrintVector<CTYPE>(val, vec_type, indent, prev_val); \
+ if (err) return err; \
+ break; }
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
}
// clang-format on
- return true;
+ return nullptr;
}
case BASE_TYPE_ARRAY: {
const auto vec_type = type.VectorType();
@@ -217,12 +222,10 @@ struct JsonPrinter {
// 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;
+ case BASE_TYPE_ ## ENUM: { \
+ auto err = PrintArray<CTYPE>(val, type.fixed_length, vec_type, indent); \
+ if (err) return err; \
+ break; }
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
// Arrays of scalars or structs are only possible.
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
@@ -230,14 +233,16 @@ struct JsonPrinter {
case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0);
}
// clang-format on
- return true;
+ return nullptr;
}
- default: FLATBUFFERS_ASSERT(0); return false;
+ default:
+ FLATBUFFERS_ASSERT(0);
+ return "unknown type";
}
}
template<typename T> static T GetFieldDefault(const FieldDef &fd) {
- T val;
+ T val{};
auto check = StringToNumber(fd.value.constant.c_str(), &val);
(void)check;
FLATBUFFERS_ASSERT(check);
@@ -246,17 +251,28 @@ struct JsonPrinter {
// Generate text for a scalar field.
template<typename T>
- bool GenField(const FieldDef &fd, const Table *table, bool fixed,
+ void 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);
+ if (fixed) {
+ PrintScalar(
+ reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset),
+ fd.value.type, indent);
+ } else if (fd.IsOptional()) {
+ auto opt = table->GetOptional<T, T>(fd.value.offset);
+ if (opt) {
+ PrintScalar(*opt, fd.value.type, indent);
+ } else {
+ text += "null";
+ }
+ } else {
+ PrintScalar(
+ 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,
+ const char *GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, const uint8_t *prev_val) {
const void *val = nullptr;
if (fixed) {
@@ -264,12 +280,18 @@ struct JsonPrinter {
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) {
+ } else if (fd.flexbuffer && opts.json_nested_flexbuffers) {
+ // We could verify this FlexBuffer before access, but since this sits
+ // inside a FlatBuffer that we don't know wether it has been verified or
+ // not, there is little point making this part safer than the parent..
+ // The caller should really be verifying the whole.
+ // If the whole buffer is corrupt, we likely crash before we even get
+ // here.
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) {
+ return nullptr;
+ } else if (fd.nested_flatbuffer && opts.json_nested_flatbuffers) {
auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
auto root = GetRoot<Table>(vec->data());
return GenStruct(*fd.nested_flatbuffer, root, indent);
@@ -283,7 +305,8 @@ struct JsonPrinter {
// 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) {
+ const char *GenStruct(const StructDef &struct_def, const Table *table,
+ int indent) {
text += '{';
int fieldout = 0;
const uint8_t *prev_val = nullptr;
@@ -307,11 +330,9 @@ struct JsonPrinter {
// 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;
+ case BASE_TYPE_ ## ENUM: { \
+ GenField<CTYPE>(fd, table, struct_def.fixed, elem_indent); \
+ break; }
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
// Generate drop-thru case statements for all pointer types:
@@ -320,10 +341,11 @@ struct JsonPrinter {
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;
+ {
+ auto err = GenFieldOffset(fd, table, struct_def.fixed, elem_indent, prev_val);
+ if (err) return err;
+ break;
+ }
}
// clang-format on
// Track prev val for use with union types.
@@ -337,7 +359,7 @@ struct JsonPrinter {
AddNewLine();
AddIndent(indent);
text += '}';
- return true;
+ return nullptr;
}
JsonPrinter(const Parser &parser, std::string &dest)
@@ -349,25 +371,26 @@ struct JsonPrinter {
std::string &text;
};
-static bool GenerateTextImpl(const Parser &parser, const Table *table,
- const StructDef &struct_def, std::string *_text) {
+static const char *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; }
+ auto err = printer.GenStruct(struct_def, table, 0);
+ if (err) return err;
printer.AddNewLine();
- return true;
+ return nullptr;
}
// Generate a text representation of a flatbuffer in JSON format.
-bool GenerateTextFromTable(const Parser &parser, const void *table,
+const char *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; }
+ if (struct_def == nullptr) { return "unknown struct"; }
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,
+const char *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)
@@ -380,21 +403,24 @@ static std::string TextFileName(const std::string &path,
return path + file_name + ".json";
}
-bool GenerateTextFile(const Parser &parser, const std::string &path,
- const std::string &file_name) {
+const char *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);
+ json.c_str(), json.size(), true)
+ ? nullptr
+ : "SaveFile failed";
}
- if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
+ if (!parser.builder_.GetSize() || !parser.root_struct_def_) return nullptr;
std::string text;
- if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
- return false;
- }
+ auto err = GenerateText(parser, parser.builder_.GetBufferPointer(), &text);
+ if (err) return err;
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(), text,
- false);
+ false)
+ ? nullptr
+ : "SaveFile failed";
}
std::string TextMakeRule(const Parser &parser, const std::string &path,
@@ -411,4 +437,65 @@ std::string TextMakeRule(const Parser &parser, const std::string &path,
return make_rule;
}
+namespace {
+
+class TextCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ auto err = GenerateTextFile(parser, path, filename);
+ if (err) {
+ status_detail = " (" + std::string(err) + ")";
+ return Status::ERROR;
+ }
+ return Status::OK;
+ }
+
+ // Generate code from the provided `buffer` of given `length`. The buffer is a
+ // serialized reflection.fbs.
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = TextMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ (void)parser;
+ (void)path;
+ (void)filename;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ bool IsSchemaOnly() const override { return false; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kJson; }
+
+ std::string LanguageName() const override { return "text"; }
+};
+
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewTextCodeGenerator() {
+ return std::unique_ptr<TextCodeGenerator>(new TextCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_text.h b/contrib/libs/flatbuffers/src/idl_gen_text.h
new file mode 100644
index 0000000000..3179a4cfa1
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_text.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 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_GEN_TEXT_H_
+#define FLATBUFFERS_IDL_GEN_TEXT_H_
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Text code generator.
+std::unique_ptr<CodeGenerator> NewTextCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_TEXT_H_
diff --git a/contrib/libs/flatbuffers/src/idl_gen_ts.cpp b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
index 53e088fe13..ca072f1c41 100644
--- a/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
+++ b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
@@ -14,28 +14,89 @@
* limitations under the License.
*/
-// independent from idl_parser, since this code is not needed for most clients
+#include "idl_gen_ts.h"
+
#include <algorithm>
#include <cassert>
+#include <cmath>
+#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flatc.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
+#include "idl_namer.h"
namespace flatbuffers {
-
+namespace {
struct ImportDefinition {
std::string name;
- std::string statement;
- const Definition *dependent;
- const Definition *dependency;
+ std::string import_statement;
+ std::string export_statement;
+ std::string bare_file_path;
+ std::string rel_file_path;
+ std::string object_name;
+ const Definition *dependent = nullptr;
+ const Definition *dependency = nullptr;
};
+struct NsDefinition {
+ std::string path;
+ std::string filepath;
+ std::string symbolic_name;
+ const Namespace *ns;
+ std::map<std::string, const Definition *> definitions;
+};
+
+Namer::Config TypeScriptDefaultConfig() {
+ return { /*types=*/Case::kKeep,
+ /*constants=*/Case::kUnknown,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kLowerCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variables=*/Case::kLowerCamel,
+ /*variants=*/Case::kKeep,
+ /*enum_variant_seperator=*/"::",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"_",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kDasher,
+ /*directories=*/Case::kDasher,
+ /*output_path=*/"",
+ /*filename_suffix=*/"_generated",
+ /*filename_extension=*/".ts" };
+}
+
+std::set<std::string> TypescriptKeywords() {
+ // List of keywords retrieved from here:
+ // https://github.com/microsoft/TypeScript/issues/2536
+ return {
+ "arguments", "break", "case", "catch", "class", "const",
+ "continue", "debugger", "default", "delete", "do", "else",
+ "enum", "export", "extends", "false", "finally", "for",
+ "function", "if", "import", "in", "instanceof", "new",
+ "null", "Object", "return", "super", "switch", "this",
+ "throw", "true", "try", "typeof", "var", "void",
+ "while", "with", "as", "implements", "interface", "let",
+ "package", "private", "protected", "public", "static", "yield",
+ };
+}
+
enum AnnotationType { kParam = 0, kType = 1, kReturns = 2 };
+template<typename T> struct SupportsObjectAPI : std::false_type {};
+
+template<> struct SupportsObjectAPI<StructDef> : std::true_type {};
+
+} // namespace
+
namespace ts {
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
@@ -45,38 +106,106 @@ class TsGenerator : public BaseGenerator {
TsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
- : BaseGenerator(parser, path, file_name, "", ".", "ts") {}
+ : BaseGenerator(parser, path, file_name, "", "_", "ts"),
+ namer_(WithFlagOptions(TypeScriptDefaultConfig(), parser.opts, path),
+ TypescriptKeywords()) {}
+
bool generate() {
generateEnums();
generateStructs();
+ generateEntry();
+ if (!generateBundle()) return false;
return true;
}
+ std::string GetTypeName(const EnumDef &def, const bool = false,
+ const bool force_ns_wrap = false) {
+ if (force_ns_wrap) { return namer_.NamespacedType(def); }
+ return namer_.Type(def);
+ }
+
+ std::string GetTypeName(const StructDef &def, const bool object_api = false,
+ const bool force_ns_wrap = false) {
+ if (object_api && parser_.opts.generate_object_based_api) {
+ if (force_ns_wrap) {
+ return namer_.NamespacedObjectType(def);
+ } else {
+ return namer_.ObjectType(def);
+ }
+ } else {
+ if (force_ns_wrap) {
+ return namer_.NamespacedType(def);
+ } else {
+ return namer_.Type(def);
+ }
+ }
+ }
+
// 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;
+ bool SaveType(const Definition &definition, const std::string &class_code,
+ import_set &imports, import_set &bare_imports) {
+ if (!class_code.length()) return true;
+
+ std::string code;
- std::string code =
- "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+ code += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
- for (auto it = bare_imports.begin(); it != bare_imports.end(); it++)
- code += it->second.statement + "\n";
+ for (auto it = bare_imports.begin(); it != bare_imports.end(); it++) {
+ code += it->second.import_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";
+ for (auto it = imports.begin(); it != imports.end(); it++) {
+ if (it->second.dependency != &definition) {
+ code += it->second.import_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);
+ code += class_code;
+
+ auto dirs = namer_.Directories(*definition.defined_namespace);
+ EnsureDirExists(dirs);
+ auto basename = dirs + namer_.File(definition, SkipFile::Suffix);
+
+ return SaveFile(basename.c_str(), code, false);
+ }
+
+ void TrackNsDef(const Definition &definition, std::string type_name) {
+ std::string path;
+ std::string filepath;
+ std::string symbolic_name;
+ if (definition.defined_namespace->components.size() > 0) {
+ path = namer_.Directories(*definition.defined_namespace,
+ SkipDir::TrailingPathSeperator);
+ filepath = path + ".ts";
+ path = namer_.Directories(*definition.defined_namespace,
+ SkipDir::OutputPathAndTrailingPathSeparator);
+ symbolic_name = definition.defined_namespace->components.back();
+ } else {
+ auto def_mod_name = namer_.File(definition, SkipFile::SuffixAndExtension);
+ symbolic_name = file_name_;
+ filepath = path_ + symbolic_name + ".ts";
+ }
+ if (ns_defs_.count(path) == 0) {
+ NsDefinition nsDef;
+ nsDef.path = path;
+ nsDef.filepath = filepath;
+ nsDef.ns = definition.defined_namespace;
+ nsDef.definitions.insert(std::make_pair(type_name, &definition));
+ nsDef.symbolic_name = symbolic_name;
+ ns_defs_[path] = nsDef;
+ } else {
+ ns_defs_[path].definitions.insert(std::make_pair(type_name, &definition));
+ }
}
private:
+ IdlNamer namer_;
+
+ std::map<std::string, NsDefinition> ns_defs_;
+
// Generate code for all enums.
void generateEnums() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
@@ -87,6 +216,8 @@ class TsGenerator : public BaseGenerator {
auto &enum_def = **it;
GenEnum(enum_def, &enumcode, imports, false);
GenEnum(enum_def, &enumcode, imports, true);
+ std::string type_name = GetTypeName(enum_def);
+ TrackNsDef(enum_def, type_name);
SaveType(enum_def, enumcode, imports, bare_imports);
}
}
@@ -101,10 +232,106 @@ class TsGenerator : public BaseGenerator {
auto &struct_def = **it;
std::string declcode;
GenStruct(parser_, struct_def, &declcode, imports);
+ std::string type_name = GetTypeName(struct_def);
+ TrackNsDef(struct_def, type_name);
SaveType(struct_def, declcode, imports, bare_imports);
}
}
+ // Generate code for a single entry point module.
+ void generateEntry() {
+ std::string code;
+
+ // add root namespace def if not already existing from defs tracking
+ std::string root;
+ if (ns_defs_.count(root) == 0) {
+ NsDefinition nsDef;
+ nsDef.path = root;
+ nsDef.symbolic_name = file_name_;
+ nsDef.filepath = path_ + file_name_ + ".ts";
+ nsDef.ns = new Namespace();
+ ns_defs_[nsDef.path] = nsDef;
+ }
+
+ for (const auto &it : ns_defs_) {
+ code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+ // export all definitions in ns entry point module
+ int export_counter = 0;
+ for (const auto &def : it.second.definitions) {
+ std::vector<std::string> rel_components;
+ // build path for root level vs child level
+ if (it.second.ns->components.size() > 1)
+ std::copy(it.second.ns->components.begin() + 1,
+ it.second.ns->components.end(),
+ std::back_inserter(rel_components));
+ else
+ std::copy(it.second.ns->components.begin(),
+ it.second.ns->components.end(),
+ std::back_inserter(rel_components));
+ auto base_file_name =
+ namer_.File(*(def.second), SkipFile::SuffixAndExtension);
+ auto base_name =
+ namer_.Directories(it.second.ns->components, SkipDir::OutputPath) +
+ base_file_name;
+ auto ts_file_path = base_name + ".ts";
+ auto base_name_rel = std::string("./");
+ base_name_rel +=
+ namer_.Directories(rel_components, SkipDir::OutputPath);
+ base_name_rel += base_file_name;
+ auto ts_file_path_rel = base_name_rel + ".ts";
+ auto type_name = def.first;
+ auto fully_qualified_type_name =
+ it.second.ns->GetFullyQualifiedName(type_name);
+ auto is_struct = parser_.structs_.Lookup(fully_qualified_type_name);
+ code += "export { " + type_name;
+ if (parser_.opts.generate_object_based_api && is_struct) {
+ code += ", " + type_name + parser_.opts.object_suffix;
+ }
+ code += " } from '";
+ std::string import_extension =
+ parser_.opts.ts_no_import_ext ? "" : ".js";
+ code += base_name_rel + import_extension + "';\n";
+ export_counter++;
+ }
+
+ // re-export child namespace(s) in parent
+ const auto child_ns_level = it.second.ns->components.size() + 1;
+ for (const auto &it2 : ns_defs_) {
+ if (it2.second.ns->components.size() != child_ns_level) continue;
+ auto ts_file_path = it2.second.path + ".ts";
+ code += "export * as " + it2.second.symbolic_name + " from './";
+ std::string rel_path = it2.second.path;
+ code += rel_path + ".js';\n";
+ export_counter++;
+ }
+
+ if (export_counter > 0) SaveFile(it.second.filepath.c_str(), code, false);
+ }
+ }
+
+ bool generateBundle() {
+ if (parser_.opts.ts_flat_files) {
+ std::string inputpath;
+ std::string symbolic_name = file_name_;
+ inputpath = path_ + file_name_ + ".ts";
+ std::string bundlepath =
+ GeneratedFileName(path_, file_name_, parser_.opts);
+ bundlepath = bundlepath.substr(0, bundlepath.size() - 3) + ".js";
+ std::string cmd = "esbuild";
+ cmd += " ";
+ cmd += inputpath;
+ // cmd += " --minify";
+ cmd += " --format=cjs --bundle --outfile=";
+ cmd += bundlepath;
+ cmd += " --external:flatbuffers";
+ std::cout << "Entry point " << inputpath << " generated." << std::endl;
+ std::cout << "A single file bundle can be created using fx. esbuild with:"
+ << std::endl;
+ std::cout << "> " << cmd << std::endl;
+ }
+ return true;
+ }
+
// Generate a documentation comment, if available.
static void GenDocComment(const std::vector<std::string> &dc,
std::string *code_ptr,
@@ -136,9 +363,9 @@ class TsGenerator : public BaseGenerator {
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";
+ code += "export enum ";
+ code += GetTypeName(enum_def);
+ code += " {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
@@ -150,11 +377,20 @@ class TsGenerator : public BaseGenerator {
if (reverse) {
code += " '" + enum_def.ToString(ev) + "'";
code += " = ";
- code += "'" + ev.name + "'";
+ code += "'" + namer_.Variant(ev) + "'";
} else {
- code += " " + ev.name;
+ code += " " + namer_.Variant(ev);
code += " = ";
- code += enum_def.ToString(ev);
+ // Unfortunately, because typescript does not support bigint enums,
+ // for 64-bit enums, we instead map the enum names to strings.
+ switch (enum_def.underlying_type.base_type) {
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ code += "'" + enum_def.ToString(ev) + "'";
+ break;
+ }
+ default: code += enum_def.ToString(ev);
+ }
}
code += (it + 1) != enum_def.Vals().end() ? ",\n" : "\n";
@@ -165,7 +401,7 @@ class TsGenerator : public BaseGenerator {
code += GenUnionConvFunc(enum_def.underlying_type, imports);
}
- code += "\n\n";
+ code += "\n";
}
static std::string GenType(const Type &type) {
@@ -200,8 +436,7 @@ class TsGenerator : public BaseGenerator {
return GenBBAccess() + ".__union_with_string" + arguments;
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
default: {
- auto getter =
- GenBBAccess() + ".read" + MakeCamel(GenType(type)) + arguments;
+ auto getter = GenBBAccess() + "." + "read" + GenType(type) + arguments;
if (type.base_type == BASE_TYPE_BOOL) { getter = "!!" + getter; }
return getter;
}
@@ -210,18 +445,43 @@ class TsGenerator : public BaseGenerator {
std::string GenBBAccess() const { return "this.bb!"; }
- std::string GenDefaultValue(const FieldDef &field, const std::string &context,
- import_set &imports) {
+ std::string GenDefaultValue(const FieldDef &field, 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_ARRAY: {
+ std::string ret = "[";
+ for (auto i = 0; i < value.type.fixed_length; ++i) {
+ std::string enum_name =
+ AddImport(imports, *value.type.enum_def, *value.type.enum_def)
+ .name;
+ std::string enum_value = namer_.Variant(
+ *value.type.enum_def->FindByValue(value.constant));
+ ret += enum_name + "." + enum_value +
+ (i < value.type.fixed_length - 1 ? ", " : "");
+ }
+ ret += "]";
+ return ret;
+ }
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ // If the value is an enum with a 64-bit base type, we have to just
+ // return the bigint value directly since typescript does not support
+ // enums with bigint backing types.
+ return "BigInt('" + value.constant + "')";
+ }
+ default: {
+ EnumVal *val = value.type.enum_def->FindByValue(value.constant);
+ if (val == nullptr)
+ val = const_cast<EnumVal *>(value.type.enum_def->MinValue());
+ return AddImport(imports, *value.type.enum_def,
+ *value.type.enum_def)
+ .name +
+ "." + namer_.Variant(*val);
+ }
}
}
@@ -234,17 +494,24 @@ class TsGenerator : public BaseGenerator {
return "null";
}
+ case BASE_TYPE_ARRAY:
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)) + ")";
+ return "BigInt('" + value.constant + "')";
}
- default: return value.constant;
+ default: {
+ if (StringIsFlatbufferNan(value.constant)) {
+ return "NaN";
+ } else if (StringIsFlatbufferPositiveInfinity(value.constant)) {
+ return "Infinity";
+ } else if (StringIsFlatbufferNegativeInfinity(value.constant)) {
+ return "-Infinity";
+ }
+ return value.constant;
+ }
}
}
@@ -257,7 +524,7 @@ class TsGenerator : public BaseGenerator {
if (IsString(type)) {
name = "string|Uint8Array";
} else {
- name = AddImport(imports, owner, *type.struct_def);
+ name = AddImport(imports, owner, *type.struct_def).name;
}
return allowNull ? (name + "|null") : name;
}
@@ -266,12 +533,28 @@ class TsGenerator : public BaseGenerator {
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";
+ case BASE_TYPE_ULONG: return allowNull ? "bigint|null" : "bigint";
+ case BASE_TYPE_ARRAY: {
+ std::string name;
+ if (type.element == BASE_TYPE_LONG || type.element == BASE_TYPE_ULONG) {
+ name = "bigint[]";
+ } else if (type.element != BASE_TYPE_STRUCT) {
+ name = "number[]";
+ } else {
+ name = "any[]";
+ if (parser_.opts.generate_object_based_api) {
+ name = "(any|" +
+ GetTypeName(*type.struct_def, /*object_api =*/true) + ")[]";
+ }
+ }
+
+ return name + (allowNull ? "|null" : "");
+ }
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
- const auto enum_name = AddImport(imports, owner, *type.enum_def);
+ const auto enum_name =
+ AddImport(imports, owner, *type.enum_def).name;
return allowNull ? (enum_name + "|null") : enum_name;
}
return allowNull ? "number|null" : "number";
@@ -281,7 +564,7 @@ class TsGenerator : public BaseGenerator {
}
// Returns the method name for use with add/put calls.
- static std::string GenWriteMethod(const Type &type) {
+ std::string GenWriteMethod(const Type &type) {
// Forward to signed versions since unsigned versions don't exist
switch (type.base_type) {
case BASE_TYPE_UTYPE:
@@ -292,7 +575,7 @@ class TsGenerator : public BaseGenerator {
default: break;
}
- return IsScalar(type.base_type) ? MakeCamel(GenType(type))
+ return IsScalar(type.base_type) ? namer_.Type(GenType(type))
: (IsStruct(type) ? "Struct" : "Offset");
}
@@ -316,15 +599,15 @@ class TsGenerator : public BaseGenerator {
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());
+ *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) {
+ 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";
@@ -339,18 +622,97 @@ class TsGenerator : public BaseGenerator {
// 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 + "_");
+ GenStructBody(
+ *field.value.type.struct_def, body,
+ nameprefix.length() ? nameprefix + "_" + field.name : 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";
+ auto element_type = field.value.type.element;
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRUCT: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i" + ") {\n";
+
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += " const item = " + fname + "?.[i];\n\n";
+
+ if (parser_.opts.generate_object_based_api) {
+ *body += " if (item instanceof " +
+ GetTypeName(*field.value.type.struct_def,
+ /*object_api =*/true) +
+ ") {\n";
+ *body += " item.pack(builder);\n";
+ *body += " continue;\n";
+ *body += " }\n\n";
+ }
+
+ std::string class_name =
+ GetPrefixedName(*field.value.type.struct_def);
+ std::string pack_func_create_call =
+ class_name + ".create" + class_name + "(builder,\n";
+ pack_func_create_call +=
+ " " +
+ GenStructMemberValueTS(*field.value.type.struct_def, "item",
+ ",\n ", false) +
+ "\n ";
+ *body += " " + pack_func_create_call;
+ *body += " );\n }\n\n";
+
+ break;
+ }
+ default: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i) {\n";
+ *body += " builder.write";
+ *body += GenWriteMethod(
+ static_cast<flatbuffers::Type>(field.value.type.element));
+ *body += "(";
+ *body += element_type == BASE_TYPE_BOOL ? "+" : "";
+
+ if (element_type == BASE_TYPE_LONG ||
+ element_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + "?.[i] ?? 0));\n";
+ } else {
+ *body += "(" + fname + "?.[i] ?? 0));\n\n";
+ }
+ *body += " }\n\n";
+ break;
+ }
+ }
+ } else {
+ std::string fname =
+ nameprefix.length() ? nameprefix + "_" + field.name : field.name;
+
+ *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ *body += "Number(Boolean(" + fname + ")));\n";
+ continue;
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + " ?? 0));\n";
+ continue;
+ }
+
+ *body += fname + ");\n";
+ }
}
}
}
std::string GenerateNewExpression(const std::string &object_name) {
- return "new " + object_name + "()";
+ return "new " + namer_.Type(object_name) + "()";
}
void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
@@ -396,16 +758,6 @@ class TsGenerator : public BaseGenerator {
}
}
- 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) {
@@ -434,7 +786,7 @@ class TsGenerator : public BaseGenerator {
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);
+ type = AddImport(imports, union_enum, *ev.union_type.struct_def).name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -448,110 +800,134 @@ class TsGenerator : public BaseGenerator {
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;
+ static bool CheckIfNameClashes(const import_set &imports,
+ const std::string &name) {
+ // TODO: this would be better as a hashset.
for (auto it = imports.begin(); it != imports.end(); it++) {
- if (it->second.name == import_name) {
- long_import_name = ns + import_name;
- break;
- }
+ if (it->second.name == name) { return true; }
}
- 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";
+ return false;
+ }
+
+ std::string GenSymbolExpression(const StructDef &struct_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &object_name) {
+ std::string symbols_expression;
+
+ if (has_name_clash) {
+ // We have a name clash
+ symbols_expression += import_name + " as " + name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " +
+ GetTypeName(struct_def, /*object_api =*/true) +
+ " as " + object_name;
+ }
} 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";
+ // No name clash, use the provided name
+ symbols_expression += name;
+
+ if (parser_.opts.generate_object_based_api) {
+ symbols_expression += ", " + object_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;
+
+ return symbols_expression;
}
- // 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 GenSymbolExpression(const EnumDef &enum_def,
+ const bool has_name_clash,
+ const std::string &import_name,
+ const std::string &name,
+ const std::string &) {
+ std::string symbols_expression;
+ if (has_name_clash) {
+ symbols_expression += import_name + " as " + name;
+ } else {
+ symbols_expression += name;
}
- 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;
+
+ if (enum_def.is_union) {
+ symbols_expression += ", unionTo" + name;
+ symbols_expression += ", unionListTo" + name;
}
- import_statement += " } from '";
- std::string file_name;
+
+ return symbols_expression;
+ }
+
+ template<typename DefinitionT>
+ ImportDefinition AddImport(import_set &imports, const Definition &dependent,
+ const DefinitionT &dependency) {
+ // The unique name of the dependency, fully qualified in its namespace.
+ const std::string unique_name = GetTypeName(
+ dependency, /*object_api = */ false, /*force_ns_wrap=*/true);
+
+ // Look if we have already added this import and return its name if found.
+ const auto import_pair = imports.find(unique_name);
+ if (import_pair != imports.end()) { return import_pair->second; }
+
+ // Check if this name would have a name clash with another type. Just use
+ // the "base" name (properly escaped) without any namespacing applied.
+ const std::string import_name = GetTypeName(dependency);
+ const bool has_name_clash = CheckIfNameClashes(imports, import_name);
+
+ // If we have a name clash, use the unique name, otherwise use simple name.
+ std::string name = has_name_clash ? unique_name : import_name;
+
+ const std::string object_name =
+ GetTypeName(dependency, /*object_api=*/true, has_name_clash);
+
+ const std::string symbols_expression = GenSymbolExpression(
+ dependency, has_name_clash, import_name, name, object_name);
+
+ std::string bare_file_path;
+ std::string rel_file_path;
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 + "';";
+ for (size_t i = 0; i < dep_comps.size(); i++) {
+ rel_file_path += i == 0 ? ".." : (kPathSeparator + std::string(".."));
+ }
+ if (dep_comps.size() == 0) { rel_file_path += "."; }
+
+ bare_file_path +=
+ kPathSeparator +
+ namer_.Directories(dependency.defined_namespace->components,
+ SkipDir::OutputPath) +
+ namer_.File(dependency, SkipFile::SuffixAndExtension);
+ rel_file_path += bare_file_path;
+
ImportDefinition import;
- import.name = long_import_name.empty() ? import_name : long_import_name;
- import.statement = import_statement;
+ import.name = name;
+ import.object_name = object_name;
+ import.bare_file_path = bare_file_path;
+ import.rel_file_path = rel_file_path;
+ std::string import_extension = parser_.opts.ts_no_import_ext ? "" : ".js";
+ import.import_statement = "import { " + symbols_expression + " } from '" +
+ rel_file_path + import_extension + "';";
+ import.export_statement = "export { " + symbols_expression + " } from '." +
+ bare_file_path + import_extension + "';";
import.dependency = &dependency;
import.dependent = &dependent;
+
imports.insert(std::make_pair(unique_name, import));
- return import.name;
+
+ return import;
}
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 + "';";
+ import.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,
+ std::string GenObjApiUnionTypeTS(import_set &imports,
+ const StructDef &dependent,
+ const IDLOptions &,
const EnumDef &union_enum) {
std::string ret = "";
std::set<std::string> type_list;
@@ -565,8 +941,8 @@ class TsGenerator : public BaseGenerator {
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);
+ type = AddImport(imports, dependent, *ev.union_type.struct_def)
+ .object_name;
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -583,11 +959,11 @@ class TsGenerator : public BaseGenerator {
}
std::string GenUnionConvFuncName(const EnumDef &enum_def) {
- return "unionTo" + enum_def.name;
+ return namer_.Function("unionTo", enum_def);
}
std::string GenUnionListConvFuncName(const EnumDef &enum_def) {
- return "unionListTo" + enum_def.name;
+ return namer_.Function("unionListTo", enum_def);
}
std::string GenUnionConvFunc(const Type &union_type, import_set &imports) {
@@ -598,12 +974,12 @@ class TsGenerator : public BaseGenerator {
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 type: " + GetTypeName(enum_def) +
",\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 enum_type = AddImport(imports, enum_def, enum_def).name;
const auto union_enum_loop = [&](const std::string &accessor_str) {
ret += " switch(" + enum_type + "[type]) {\n";
@@ -614,13 +990,13 @@ class TsGenerator : public BaseGenerator {
const auto &ev = **it;
if (ev.IsZero()) { continue; }
- ret += " case '" + ev.name + "': ";
+ ret += " case '" + namer_.Variant(ev) + "': ";
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);
+ AddImport(imports, enum_def, *ev.union_type.struct_def).name;
ret += "return " + accessor_str + "new " + type + "())! as " +
type + ";";
} else {
@@ -637,7 +1013,7 @@ class TsGenerator : public BaseGenerator {
ret += "}";
ret += "\n\nexport function " + GenUnionListConvFuncName(enum_def) +
- "(\n type: " + enum_def.name +
+ "(\n type: " + GetTypeName(enum_def) +
", \n accessor: (index: number, obj:" + valid_union_type +
") => " + valid_union_type_with_null +
", \n index: number\n): " + valid_union_type_with_null + " {\n";
@@ -653,12 +1029,13 @@ class TsGenerator : public BaseGenerator {
// 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,
+ std::string GenUnionValTS(import_set &imports, const StructDef &dependent,
+ 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 auto enum_type = AddImport(imports, dependent, enum_def).name;
const std::string union_accessor = "this." + field_name;
const auto union_has_string = UnionHasStringType(enum_def);
@@ -668,11 +1045,11 @@ class TsGenerator : public BaseGenerator {
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 += " const temp = " + conversion_function + "(this." +
+ namer_.Method(field_name, "Type") + "(), " +
+ field_binded_method + ");\n";
ret += " if(temp === null) { return null; }\n";
ret += union_has_string
? " if(typeof temp === 'string') { return temp; }\n"
@@ -681,21 +1058,22 @@ class TsGenerator : public BaseGenerator {
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 +
+ ret += " const ret: (" +
+ GenObjApiUnionTypeTS(imports, *union_type.struct_def,
+ parser_.opts, *union_type.enum_def) +
+ ")[] = [];\n";
+ ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
+ namer_.Method(field_name, "TypeLength") + "()" +
"; "
"++targetEnumIndex) {\n";
- ret += " let targetEnum = " + target_enum_accesor +
- "(targetEnumIndex);\n";
+ ret += " const targetEnum = this." +
+ namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
ret += " if(targetEnum === null || " + enum_type +
"[targetEnum!] === 'NONE') { "
"continue; }\n\n";
- ret += " let temp = " + conversion_function + "(targetEnum, " +
+ ret += " const temp = " + conversion_function + "(targetEnum, " +
field_binded_method + ", targetEnumIndex);\n";
ret += " if(temp === null) { continue; }\n";
ret += union_has_string ? " if(typeof temp === 'string') { "
@@ -730,15 +1108,25 @@ class TsGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
- const auto curr_member_accessor =
- prefix + "." + MakeCamel(field.name, false);
+ auto curr_member_accessor = prefix + "." + namer_.Method(field);
+ if (prefix != "this") {
+ curr_member_accessor = prefix + "?." + namer_.Method(field);
+ }
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 + "!)";
+ std::string nullValue = "0";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ nullValue = "false";
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ nullValue = "BigInt(0)";
+ } else if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ nullValue = "[]";
+ }
+ ret += "(" + curr_member_accessor + " ?? " + nullValue + ")";
} else {
ret += curr_member_accessor;
}
@@ -753,7 +1141,7 @@ class TsGenerator : public BaseGenerator {
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);
+ const auto class_name = GetTypeName(struct_def, /*object_api=*/true);
std::string unpack_func = "\nunpack(): " + class_name +
" {\n return new " + class_name + "(" +
@@ -773,7 +1161,7 @@ class TsGenerator : public BaseGenerator {
std::string pack_func_offset_decl;
std::string pack_func_create_call;
- const auto struct_name = AddImport(imports, struct_def, struct_def);
+ const auto struct_name = AddImport(imports, struct_def, struct_def).name;
if (has_create) {
pack_func_create_call = " return " + struct_name + ".create" +
@@ -796,9 +1184,10 @@ class TsGenerator : public BaseGenerator {
auto &field = **it;
if (field.deprecated) continue;
- const auto field_name = MakeCamel(field.name, false);
+ const auto field_method = namer_.Method(field);
+ const auto field_field = namer_.Field(field);
const std::string field_binded_method =
- "this." + field_name + ".bind(this)";
+ "this." + field_method + ".bind(this)";
std::string field_val;
std::string field_type;
@@ -809,8 +1198,7 @@ class TsGenerator : public BaseGenerator {
// 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);
+ const auto field_default_val = GenDefaultValue(field, imports);
// Emit a scalar field
const auto is_string = IsString(field.value.type);
@@ -819,14 +1207,14 @@ class TsGenerator : public BaseGenerator {
field_type += GenTypeName(imports, field, field.value.type, false,
has_null_default);
- field_val = "this." + field_name + "()";
+ field_val = "this." + namer_.Method(field) + "()";
if (field.value.type.base_type != BASE_TYPE_STRING) {
- field_offset_val = "this." + field_name;
+ field_offset_val = "this." + namer_.Field(field);
} else {
field_offset_decl = GenNullCheckConditional(
- "this." + field_name,
- "builder.createString(this." + field_name + "!)", "0");
+ "this." + namer_.Field(field),
+ "builder.createString(this." + field_field + "!)", "0");
}
}
@@ -836,14 +1224,15 @@ class TsGenerator : public BaseGenerator {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(sd, parser.opts);
+ field_type += AddImport(imports, struct_def, sd).object_name;
- const std::string field_accessor = "this." + field_name + "()";
+ const std::string field_accessor =
+ "this." + namer_.Method(field) + "()";
field_val = GenNullCheckConditional(field_accessor,
field_accessor + "!.unpack()");
auto packing = GenNullCheckConditional(
- "this." + field_name, "this." + field_name + "!.pack(builder)",
- "0");
+ "this." + field_field,
+ "this." + field_field + "!.pack(builder)", "0");
if (sd.fixed) {
field_offset_val = std::move(packing);
@@ -854,6 +1243,95 @@ class TsGenerator : public BaseGenerator {
break;
}
+ case BASE_TYPE_ARRAY: {
+ 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;
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
+ field_type += ")[]";
+
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
+ field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
+
+ if (sd.fixed) {
+ field_offset_decl =
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
+ } else {
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_STRING: {
+ field_type += "string)[]";
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
+ field_type += ")[]";
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+
+ 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<" +
+ vectortypename + ">(" + field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
+
+ break;
+ }
+ }
+
+ break;
+ }
+
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
@@ -865,24 +1343,27 @@ class TsGenerator : public BaseGenerator {
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetObjApiClassName(sd, parser.opts);
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
field_type += ")[]";
- field_val = GenBBAccess() + ".createObjList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
+ field_binded_method + ", this." +
+ namer_.Method(field, "Length") + "())";
if (sd.fixed) {
field_offset_decl =
- "builder.createStructOffsetList(this." + field_name +
- ", " + AddImport(imports, struct_def, struct_def) +
- ".start" + MakeCamel(field_name) + "Vector)";
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
} else {
field_offset_decl =
- AddImport(imports, struct_def, struct_def) + ".create" +
- MakeCamel(field_name) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
}
break;
@@ -890,29 +1371,29 @@ class TsGenerator : public BaseGenerator {
case BASE_TYPE_STRING: {
field_type += "string)[]";
- field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
field_offset_decl =
- AddImport(imports, struct_def, struct_def) + ".create" +
- MakeCamel(field_name) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
break;
}
case BASE_TYPE_UNION: {
- field_type += GenObjApiUnionTypeTS(imports, parser.opts,
- *(vectortype.enum_def));
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
field_type += ")[]";
- field_val =
- GenUnionValTS(imports, field_name, vectortype, true);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
field_offset_decl =
- AddImport(imports, struct_def, struct_def) + ".create" +
- MakeCamel(field_name) +
- "Vector(builder, builder.createObjectOffsetList(" +
- "this." + field_name + "))";
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
break;
}
@@ -924,13 +1405,14 @@ class TsGenerator : public BaseGenerator {
field_type += vectortypename;
}
field_type += ")[]";
- field_val = GenBBAccess() + ".createScalarList(" +
- field_binded_method + ", this." + field_name +
- "Length())";
+ field_val = GenBBAccess() + ".createScalarList<" +
+ vectortypename + ">(" + field_binded_method +
+ ", this." + namer_.Method(field, "Length") + "())";
- field_offset_decl = AddImport(imports, struct_def, struct_def) +
- ".create" + MakeCamel(field_name) +
- "Vector(builder, this." + field_name + ")";
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
break;
}
@@ -940,12 +1422,13 @@ class TsGenerator : public BaseGenerator {
}
case BASE_TYPE_UNION: {
- field_type += GenObjApiUnionTypeTS(imports, parser.opts,
+ field_type += GenObjApiUnionTypeTS(imports, struct_def, parser.opts,
*(field.value.type.enum_def));
- field_val = GenUnionValTS(imports, field_name, field.value.type);
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ field.value.type);
field_offset_decl =
- "builder.createObjectOffset(this." + field_name + ")";
+ "builder.createObjectOffset(this." + field_field + ")";
break;
}
@@ -958,15 +1441,17 @@ class TsGenerator : public BaseGenerator {
if (!field_offset_decl.empty()) {
field_offset_decl =
- " const " + field_name + " = " + field_offset_decl + ";";
+ " const " + field_field + " = " + field_offset_decl + ";";
}
- if (field_offset_val.empty()) { field_offset_val = field_name; }
+ if (field_offset_val.empty()) { field_offset_val = field_field; }
unpack_func += " " + field_val;
- unpack_to_func += " _o." + field_name + " = " + field_val + ";";
+ unpack_to_func += " _o." + field_field + " = " + field_val + ";";
- constructor_func += " public " + field_name + ": " + field_type + " = " +
- field_default_val;
+ // FIXME: if field_type and field_field are identical, then
+ // this generates invalid typescript.
+ constructor_func += " public " + field_field + ": " + field_type +
+ " = " + field_default_val;
if (!struct_def.fixed) {
if (!field_offset_decl.empty()) {
@@ -976,8 +1461,12 @@ class TsGenerator : public BaseGenerator {
if (has_create) {
pack_func_create_call += field_offset_val;
} else {
- pack_func_create_call += " " + struct_name + ".add" +
- MakeCamel(field.name) + "(builder, " +
+ if (field.IsScalarOptional()) {
+ pack_func_create_call +=
+ " if (" + field_offset_val + " !== null)\n ";
+ }
+ pack_func_create_call += " " + struct_name + "." +
+ namer_.Method("add", field) + "(builder, " +
field_offset_val + ");\n";
}
}
@@ -1011,10 +1500,10 @@ class TsGenerator : public BaseGenerator {
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 = "\n";
+ obj_api_class += "export class ";
+ obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
+ obj_api_class += " implements flatbuffers.IGeneratedObject {\n";
obj_api_class += constructor_func;
obj_api_class += pack_func_prototype + pack_func_offset_decl +
pack_func_create_call + "\n}";
@@ -1045,21 +1534,31 @@ class TsGenerator : public BaseGenerator {
if (struct_def.generated) return;
std::string &code = *code_ptr;
- std::string object_name;
- std::string object_namespace = GetNameSpace(struct_def);
+ // Special case for the root struct, since no one will necessarily reference
+ // it, we have to explicitly add it to the import list.
+ if (&struct_def == parser_.root_struct_def_) {
+ AddImport(imports, struct_def, struct_def);
+ }
+
+ const std::string object_name = GetTypeName(struct_def);
+ const std::string object_api_name = GetTypeName(struct_def, true);
// Emit constructor
- object_name = struct_def.name;
GenDocComment(struct_def.doc_comment, code_ptr);
- code += "export class " + struct_def.name;
- code += " {\n";
+ code += "export class ";
+ code += object_name;
+ if (parser.opts.generate_object_based_api)
+ code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
+ "> {\n";
+ else
+ 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";
+ " __init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
code += " this.bb_pos = i;\n";
code += " this.bb = bb;\n";
code += " return this;\n";
@@ -1086,9 +1585,16 @@ class TsGenerator : public BaseGenerator {
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 ? ";
+ std::string offset_prefix = "";
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ offset_prefix = " return ";
+ } else {
+ offset_prefix = " const offset = " + GenBBAccess() +
+ ".__offset(this.bb_pos, " +
+ NumToString(field.value.offset) + ");\n";
+ offset_prefix += " return offset ? ";
+ }
// Emit a scalar field
const auto is_string = IsString(field.value.type);
@@ -1096,7 +1602,7 @@ class TsGenerator : public BaseGenerator {
const auto has_null_default = is_string || HasNullDefault(field);
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = MakeCamel(field.name, false) + "(";
+ std::string prefix = namer_.Method(field) + "(";
if (is_string) {
code += prefix + "):string|null\n";
code +=
@@ -1128,9 +1634,11 @@ class TsGenerator : public BaseGenerator {
} 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 +=
+ offset_prefix + GenGetter(field.value.type, "(" + index + ")");
+ if (field.value.type.base_type != BASE_TYPE_ARRAY) {
+ code += " : " + GenDefaultValue(field, imports);
+ }
code += ";\n";
}
}
@@ -1140,9 +1648,10 @@ class TsGenerator : public BaseGenerator {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
const auto type =
- AddImport(imports, struct_def, *field.value.type.struct_def);
+ AddImport(imports, struct_def, *field.value.type.struct_def)
+ .name;
GenDocComment(field.doc_comment, code_ptr);
- code += MakeCamel(field.name, false);
+ code += namer_.Method(field);
code += "(obj?:" + type + "):" + type + "|null {\n";
if (struct_def.fixed) {
@@ -1162,6 +1671,95 @@ class TsGenerator : public BaseGenerator {
break;
}
+ case BASE_TYPE_ARRAY: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ auto inline_size = InlineSize(vectortype);
+ auto index = "this.bb_pos + " + NumToString(field.value.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 = namer_.Method(field);
+ // 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 + ")");
+ }
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ break;
+ }
+ case BASE_TYPE_BOOL: {
+ code += " : false";
+ break;
+ }
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ code += " : BigInt(0)";
+ break;
+ }
+ default: {
+ if (IsScalar(field.value.type.element)) {
+ if (field.value.type.enum_def) {
+ code += field.value.constant;
+ } else {
+ code += " : 0";
+ }
+ } else {
+ code += ": null";
+ }
+ break;
+ }
+ }
+ code += ";\n";
+ break;
+ }
+
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
@@ -1182,7 +1780,7 @@ class TsGenerator : public BaseGenerator {
default: ret_type = vectortypename;
}
GenDocComment(field.doc_comment, code_ptr);
- std::string prefix = MakeCamel(field.name, false);
+ std::string prefix = namer_.Method(field);
// TODO: make it work without any
// if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
if (is_union) { prefix += ""; }
@@ -1226,7 +1824,7 @@ class TsGenerator : public BaseGenerator {
code += "false";
} else if (field.value.type.element == BASE_TYPE_LONG ||
field.value.type.element == BASE_TYPE_ULONG) {
- code += GenBBAccess() + ".createLong(0, 0)";
+ code += "BigInt(0)";
} else if (IsScalar(field.value.type.element)) {
if (field.value.type.enum_def) {
code += field.value.constant;
@@ -1242,7 +1840,7 @@ class TsGenerator : public BaseGenerator {
case BASE_TYPE_UNION: {
GenDocComment(field.doc_comment, code_ptr);
- code += MakeCamel(field.name, false);
+ code += namer_.Method(field);
const auto &union_enum = *(field.value.type.enum_def);
const auto union_type = GenUnionGenericTypeTS(union_enum);
@@ -1267,11 +1865,14 @@ class TsGenerator : public BaseGenerator {
std::string type =
GenTypeName(imports, struct_def, field.value.type, true);
- code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
+ code += namer_.LegacyTsMutateMethod(field) + "(value:" + type +
+ "):boolean {\n";
+
+ const std::string write_method =
+ "." + namer_.Method("write", GenType(field.value.type));
if (struct_def.fixed) {
- code += " " + GenBBAccess() + ".write" +
- MakeCamel(GenType(field.value.type)) + "(this.bb_pos + " +
+ code += " " + GenBBAccess() + write_method + "(this.bb_pos + " +
NumToString(field.value.offset) + ", ";
} else {
code += " const offset = " + GenBBAccess() +
@@ -1282,9 +1883,8 @@ class TsGenerator : public BaseGenerator {
code += " }\n\n";
// special case for bools, which are treated as uint8
- code += " " + GenBBAccess() + ".write" +
- MakeCamel(GenType(field.value.type)) +
- "(this.bb_pos + offset, ";
+ code +=
+ " " + GenBBAccess() + write_method + "(this.bb_pos + offset, ";
if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
}
@@ -1297,8 +1897,8 @@ class TsGenerator : public BaseGenerator {
if (IsVector(field.value.type)) {
// Emit a length helper
GenDocComment(code_ptr);
- code += MakeCamel(field.name, false);
- code += "Length():number {\n" + offset_prefix;
+ code += namer_.Method(field, "Length");
+ code += "():number {\n" + offset_prefix;
code +=
GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
@@ -1308,9 +1908,9 @@ class TsGenerator : public BaseGenerator {
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 += namer_.Method(field, "Array");
+ code +=
+ "():" + GenType(vectorType) + "Array|null {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
".bytes().buffer, " + GenBBAccess() +
@@ -1325,7 +1925,10 @@ class TsGenerator : public BaseGenerator {
if (parser_.opts.generate_name_strings) {
GenDocComment(code_ptr);
code += "static getFullyQualifiedName():string {\n";
- code += " return '" + WrapInNameSpace(struct_def) + "';\n";
+ code +=
+ " return '" +
+ struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name) +
+ "';\n";
code += "}\n\n";
}
@@ -1369,7 +1972,7 @@ class TsGenerator : public BaseGenerator {
// Generate the field insertion method
GenDocComment(code_ptr);
- code += "static add" + MakeCamel(field.name);
+ code += "static " + namer_.Method("add", field);
code += "(builder:flatbuffers.Builder, " + argname + ":" +
GetArgType(imports, struct_def, field, false) + ") {\n";
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
@@ -1380,13 +1983,13 @@ class TsGenerator : public BaseGenerator {
code += "0";
} else if (HasNullDefault(field)) {
if (IsLong(field.value.type.base_type)) {
- code += "builder.createLong(0, 0)";
+ code += "BigInt(0)";
} else {
code += "0";
}
} else {
if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
- code += GenDefaultValue(field, "builder", imports);
+ code += GenDefaultValue(field, imports);
}
code += ");\n}\n\n";
@@ -1400,8 +2003,8 @@ class TsGenerator : public BaseGenerator {
GenDocComment(code_ptr);
const std::string sig_begin =
- "static create" + MakeCamel(field.name) +
- "Vector(builder:flatbuffers.Builder, data:";
+ "static " + namer_.Method("create", field, "Vector") +
+ "(builder:flatbuffers.Builder, data:";
const std::string sig_end = "):flatbuffers.Offset";
std::string type =
GenTypeName(imports, struct_def, vector_type, true) + "[]";
@@ -1438,8 +2041,9 @@ class TsGenerator : public BaseGenerator {
// after
GenDocComment(code_ptr);
- code += "static start" + MakeCamel(field.name);
- code += "Vector(builder:flatbuffers.Builder, numElems:number) {\n";
+ code += "static ";
+ code += namer_.Method("start", field, "Vector");
+ code += "(builder:flatbuffers.Builder, numElems:number) {\n";
code += " builder.startVector(" + NumToString(elem_size);
code += ", numElems, " + NumToString(alignment) + ");\n";
code += "}\n\n";
@@ -1482,10 +2086,10 @@ class TsGenerator : public BaseGenerator {
}
code += "):flatbuffers.Offset {\n";
- code += " " + struct_def.name + ".start" +
- GetPrefixedName(struct_def) + "(builder);\n";
+ code += " " + object_name + ".start" + GetPrefixedName(struct_def) +
+ "(builder);\n";
- std::string methodPrefix = struct_def.name;
+ std::string methodPrefix = object_name;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
@@ -1497,7 +2101,7 @@ class TsGenerator : public BaseGenerator {
code += " if (" + arg_name + " !== null)\n ";
}
- code += " " + methodPrefix + ".add" + MakeCamel(field.name) + "(";
+ code += " " + methodPrefix + "." + namer_.Method("add", field) + "(";
code += "builder, " + arg_name + ");\n";
}
@@ -1515,8 +2119,9 @@ class TsGenerator : public BaseGenerator {
code += "}\n";
code += "\n";
- code += "static deserialize(buffer: Uint8Array):" + name + " {\n";
- code += " return " + AddImport(imports, struct_def, struct_def) +
+ code += "static deserialize(buffer: Uint8Array):" +
+ namer_.EscapeKeyword(name) + " {\n";
+ code += " return " + AddImport(imports, struct_def, struct_def).name +
".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
code += "}\n";
}
@@ -1543,10 +2148,9 @@ class TsGenerator : public BaseGenerator {
allowNull && field.IsOptional());
}
- static std::string GetArgName(const FieldDef &field) {
- auto argname = MakeCamel(field.name, false);
+ std::string GetArgName(const FieldDef &field) {
+ auto argname = namer_.Variable(field);
if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
-
return argname;
}
@@ -1565,8 +2169,6 @@ bool GenerateTS(const Parser &parser, const std::string &path,
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);
@@ -1580,4 +2182,54 @@ std::string TSMakeRule(const Parser &parser, const std::string &path,
return make_rule;
}
+namespace {
+
+class TsCodeGenerator : public CodeGenerator {
+ public:
+ Status GenerateCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateTS(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateCode(const uint8_t *buffer, int64_t length) override {
+ (void)buffer;
+ (void)length;
+ return Status::NOT_IMPLEMENTED;
+ }
+
+ Status GenerateMakeRule(const Parser &parser, const std::string &path,
+ const std::string &filename,
+ std::string &output) override {
+ output = TSMakeRule(parser, path, filename);
+ return Status::OK;
+ }
+
+ Status GenerateGrpcCode(const Parser &parser, const std::string &path,
+ const std::string &filename) override {
+ if (!GenerateTSGRPC(parser, path, filename)) { return Status::ERROR; }
+ return Status::OK;
+ }
+
+ Status GenerateRootFile(const Parser &parser,
+ const std::string &path) override {
+ (void)parser;
+ (void)path;
+ return Status::NOT_IMPLEMENTED;
+ }
+ bool IsSchemaOnly() const override { return true; }
+
+ bool SupportsBfbsGeneration() const override { return false; }
+ bool SupportsRootFileGeneration() const override { return false; }
+
+ IDLOptions::Language Language() const override { return IDLOptions::kTs; }
+
+ std::string LanguageName() const override { return "TS"; }
+};
+} // namespace
+
+std::unique_ptr<CodeGenerator> NewTsCodeGenerator() {
+ return std::unique_ptr<TsCodeGenerator>(new TsCodeGenerator());
+}
+
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_ts.h b/contrib/libs/flatbuffers/src/idl_gen_ts.h
new file mode 100644
index 0000000000..d2ece2dd96
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_ts.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 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_GEN_TS_H_
+#define FLATBUFFERS_IDL_GEN_TS_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/code_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Ts code generator.
+std::unique_ptr<CodeGenerator> NewTsCodeGenerator();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_GEN_TS_H_
diff --git a/contrib/libs/flatbuffers/src/idl_namer.h b/contrib/libs/flatbuffers/src/idl_namer.h
new file mode 100644
index 0000000000..7f89433da6
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_namer.h
@@ -0,0 +1,177 @@
+#ifndef FLATBUFFERS_IDL_NAMER
+#define FLATBUFFERS_IDL_NAMER
+
+#include "flatbuffers/idl.h"
+#include "namer.h"
+
+namespace flatbuffers {
+
+// Provides Namer capabilities to types defined in the flatbuffers IDL.
+class IdlNamer : public Namer {
+ public:
+ explicit IdlNamer(Config config, std::set<std::string> keywords)
+ : Namer(config, std::move(keywords)) {}
+
+ using Namer::Constant;
+ using Namer::Directories;
+ using Namer::Field;
+ using Namer::File;
+ using Namer::Function;
+ using Namer::Method;
+ using Namer::Namespace;
+ using Namer::NamespacedType;
+ using Namer::ObjectType;
+ using Namer::Type;
+ using Namer::Variable;
+ using Namer::Variant;
+
+ std::string Constant(const FieldDef &d) const { return Constant(d.name); }
+
+ // Types are always structs or enums so we can only expose these two
+ // overloads.
+ std::string Type(const StructDef &d) const { return Type(d.name); }
+ std::string Type(const EnumDef &d) const { return Type(d.name); }
+
+ std::string Function(const Definition &s) const { return Function(s.name); }
+ std::string Function(const std::string& prefix, const Definition &s) const {
+ return Function(prefix + s.name);
+ }
+
+ std::string Field(const FieldDef &s) const { return Field(s.name); }
+ std::string Field(const FieldDef &d, const std::string &s) const {
+ return Field(d.name + "_" + s);
+ }
+
+ std::string Variable(const FieldDef &s) const { return Variable(s.name); }
+
+ std::string Variable(const StructDef &s) const { return Variable(s.name); }
+
+ std::string Variant(const EnumVal &s) const { return Variant(s.name); }
+
+ std::string EnumVariant(const EnumDef &e, const EnumVal &v) const {
+ return Type(e) + config_.enum_variant_seperator + Variant(v);
+ }
+
+ std::string ObjectType(const StructDef &d) const {
+ return ObjectType(d.name);
+ }
+ std::string ObjectType(const EnumDef &d) const { return ObjectType(d.name); }
+
+ std::string Method(const FieldDef &d, const std::string &suffix) const {
+ return Method(d.name, suffix);
+ }
+ std::string Method(const std::string &prefix, const StructDef &d) const {
+ return Method(prefix, d.name);
+ }
+ std::string Method(const std::string &prefix, const FieldDef &d) const {
+ return Method(prefix, d.name);
+ }
+ std::string Method(const std::string &prefix, const FieldDef &d,
+ const std::string &suffix) const {
+ return Method(prefix, d.name, suffix);
+ }
+
+ std::string Namespace(const struct Namespace &ns) const {
+ return Namespace(ns.components);
+ }
+
+ std::string NamespacedEnumVariant(const EnumDef &e, const EnumVal &v) const {
+ return NamespacedString(e.defined_namespace, EnumVariant(e, v));
+ }
+
+ std::string NamespacedType(const Definition &def) const {
+ return NamespacedString(def.defined_namespace, Type(def.name));
+ }
+
+ std::string NamespacedObjectType(const Definition &def) const {
+ return NamespacedString(def.defined_namespace, ObjectType(def.name));
+ }
+
+ std::string Directories(const struct Namespace &ns,
+ SkipDir skips = SkipDir::None) const {
+ return Directories(ns.components, skips);
+ }
+
+ // Legacy fields do not really follow the usual config and should be
+ // considered for deprecation.
+
+ std::string LegacyRustNativeVariant(const EnumVal &v) const {
+ return ConvertCase(EscapeKeyword(v.name), Case::kUpperCamel);
+ }
+
+ std::string LegacyRustFieldOffsetName(const FieldDef &field) const {
+ return "VT_" + ConvertCase(EscapeKeyword(field.name), Case::kAllUpper);
+ }
+ std::string LegacyRustUnionTypeOffsetName(const FieldDef &field) const {
+ return "VT_" + ConvertCase(EscapeKeyword(field.name + "_type"), Case::kAllUpper);
+ }
+
+
+ std::string LegacySwiftVariant(const EnumVal &ev) const {
+ auto name = ev.name;
+ if (isupper(name.front())) {
+ std::transform(name.begin(), name.end(), name.begin(), CharToLower);
+ }
+ return EscapeKeyword(ConvertCase(name, Case::kLowerCamel));
+ }
+
+ // Also used by Kotlin, lol.
+ std::string LegacyJavaMethod2(const std::string &prefix, const StructDef &sd,
+ const std::string &suffix) const {
+ return prefix + sd.name + suffix;
+ }
+
+ std::string LegacyKotlinVariant(EnumVal &ev) const {
+ // Namer assumes the input case is snake case which is wrong...
+ return ConvertCase(EscapeKeyword(ev.name), Case::kLowerCamel);
+ }
+ // Kotlin methods escapes keywords after case conversion but before
+ // prefixing and suffixing.
+ std::string LegacyKotlinMethod(const std::string &prefix, const FieldDef &d,
+ const std::string &suffix) const {
+ return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
+ suffix;
+ }
+ std::string LegacyKotlinMethod(const std::string &prefix, const StructDef &d,
+ const std::string &suffix) const {
+ return prefix + ConvertCase(EscapeKeyword(d.name), Case::kUpperCamel) +
+ suffix;
+ }
+
+ // This is a mix of snake case and keep casing, when Ts should be using
+ // lower camel case.
+ std::string LegacyTsMutateMethod(const FieldDef& d) {
+ return "mutate_" + d.name;
+ }
+
+ std::string LegacyRustUnionTypeMethod(const FieldDef &d) {
+ // assert d is a union
+ return Method(d.name + "_type");
+ }
+
+ private:
+ std::string NamespacedString(const struct Namespace *ns,
+ const std::string &str) const {
+ std::string ret;
+ if (ns != nullptr) { ret += Namespace(ns->components); }
+ if (!ret.empty()) ret += config_.namespace_seperator;
+ return ret + str;
+ }
+};
+
+// This is a temporary helper function for code generators to call until all
+// flag-overriding logic into flatc.cpp
+inline Namer::Config WithFlagOptions(const Namer::Config &input,
+ const IDLOptions &opts,
+ const std::string &path) {
+ Namer::Config result = input;
+ result.object_prefix = opts.object_prefix;
+ result.object_suffix = opts.object_suffix;
+ result.output_path = path;
+ result.filename_suffix = opts.filename_suffix;
+ return result;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_NAMER
diff --git a/contrib/libs/flatbuffers/src/idl_parser.cpp b/contrib/libs/flatbuffers/src/idl_parser.cpp
index ad642d79a9..bddc736a5f 100644
--- a/contrib/libs/flatbuffers/src/idl_parser.cpp
+++ b/contrib/libs/flatbuffers/src/idl_parser.cpp
@@ -16,11 +16,15 @@
#include <algorithm>
#include <cmath>
+#include <iostream>
#include <list>
#include <string>
#include <utility>
+#include "flatbuffers/base.h"
+#include "flatbuffers/buffer.h"
#include "flatbuffers/idl.h"
+#include "flatbuffers/reflection_generated.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
@@ -35,28 +39,14 @@ const char *FLATBUFFERS_VERSION() {
// clang-format on
}
-const double kPi = 3.14159265358979323846;
+namespace {
-// 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
+static const double kPi = 3.14159265358979323846;
// 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),
+static_assert(BASE_TYPE_VECTOR64 ==
+ static_cast<BaseType>(reflection::MaxBaseType - 1),
"enums don't match");
// Any parsing calls have to be wrapped in this macro, which automates
@@ -92,117 +82,36 @@ static bool IsLowerSnakeCase(const std::string &str) {
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) {
+static 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); }
+static 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() {
+template<typename T> static 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>) {
+static 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>) {
+static 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) {
+template<typename T>
+static 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)
@@ -212,33 +121,26 @@ template<typename T> CheckedError atot(const char *s, Parser &parser, T *val) {
", constant does not fit " + TypeToIntervalString<T>());
}
template<>
-inline CheckedError atot<Offset<void>>(const char *s, Parser &parser,
- Offset<void> *val) {
+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<>
+CheckedError atot<Offset64<void>>(const char *s, Parser &parser,
+ Offset64<void> *val) {
+ (void)parser;
+ *val = Offset64<void>(atoi(s));
+ return NoError();
}
template<typename T>
-T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
- const Namespace &current_namespace, size_t skip_top) {
+static 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;
@@ -297,6 +199,254 @@ static std::string TokenToString(int t) {
}
// clang-format on
+static bool IsIdentifierStart(char c) { return is_alpha(c) || (c == '_'); }
+
+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>
+static 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);
+}
+
+template<typename T> static 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 void SingleValueRepack(Value &e, float val) {
+ if (val != val) e.constant = "nan";
+}
+static void SingleValueRepack(Value &e, double val) {
+ if (val != val) e.constant = "nan";
+}
+#endif
+
+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);
+}
+
+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;
+}
+
+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;
+}
+
+// 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;
+}
+
+template<typename T> static bool compareName(const T *a, const T *b) {
+ return a->defined_namespace->GetFullyQualifiedName(a->name) <
+ b->defined_namespace->GetFullyQualifiedName(b->name);
+}
+
+template<typename T> static 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;
+}
+
+} // namespace
+
+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);
+ has_warning_ = true; // for opts.warnings_as_errors
+ }
+}
+
+CheckedError Parser::Error(const std::string &msg) {
+ Message("error: " + msg);
+ return CheckedError(true);
+}
+
+CheckedError Parser::RecurseError() {
+ return Error("maximum parsing depth " + NumToString(parse_depth_counter_) +
+ " reached");
+}
+
+const std::string &Parser::GetPooledString(const std::string &s) const {
+ return *(string_cache_.insert(s).first);
+}
+
+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_;
+};
+
+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;
+}
+
std::string Parser::TokenToStringId(int t) const {
return t == kTokenIdentifier ? attribute_ : TokenToString(t);
}
@@ -326,12 +476,9 @@ CheckedError Parser::SkipByteOrderMark() {
return NoError();
}
-static inline bool IsIdentifierStart(char c) {
- return is_alpha(c) || (c == '_');
-}
-
CheckedError Parser::Next() {
doc_comment_.clear();
+ prev_cursor_ = cursor_;
bool seen_newline = cursor_ == source_;
attribute_.clear();
attr_is_trivial_ascii_string_ = true;
@@ -356,6 +503,8 @@ CheckedError Parser::Next() {
case ')':
case '[':
case ']':
+ case '<':
+ case '>':
case ',':
case ':':
case ';':
@@ -508,10 +657,21 @@ CheckedError Parser::Next() {
}
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();
+ if (has_sign) {
+ // Check for +/-inf which is considered a float constant.
+ if (strncmp(cursor_, "inf", 3) == 0 &&
+ !(IsIdentifierStart(cursor_[3]) || is_digit(cursor_[3]))) {
+ attribute_.assign(cursor_ - 1, cursor_ + 3);
+ token_ = kTokenFloatConstant;
+ cursor_ += 3;
+ return NoError();
+ }
+
+ if (IsIdentifierStart(*cursor_)) {
+ // '-'/'+' and following identifier - it could be a predefined
+ // constant. Return the sign in token_, see ParseSingleValue.
+ return NoError();
+ }
}
auto dot_lvl =
@@ -753,6 +913,15 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
ECHECK(ParseType(type));
if (struct_def.fixed) {
+ if (IsIncompleteStruct(type) ||
+ (IsArray(type) && IsIncompleteStruct(type.VectorType()))) {
+ std::string type_name = IsArray(type) ? type.VectorType().struct_def->name
+ : type.struct_def->name;
+ return Error(
+ std::string("Incomplete type in struct is not allowed, type name: ") +
+ type_name);
+ }
+
auto valid = IsScalar(type.base_type) || IsStruct(type);
if (!valid && IsArray(type)) {
const auto &elem_type = type.VectorType();
@@ -799,6 +968,14 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
FieldDef *field;
ECHECK(AddField(struct_def, name, type, &field));
+ if (typefield) {
+ // We preserve the relation between the typefield
+ // and field, so we can easily map it in the code
+ // generators.
+ typefield->sibling_union_field = field;
+ field->sibling_union_field = typefield;
+ }
+
if (token_ == '=') {
NEXT();
ECHECK(ParseSingleValue(&field->name, field->value, true));
@@ -808,8 +985,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
"or in structs.");
if (IsString(type) || IsVector(type)) {
advanced_features_ |= reflection::DefaultVectorsAndStrings;
- if (field->value.constant != "0" && field->value.constant != "null" &&
- !SupportsDefaultVectorsAndStrings()) {
+ if (field->value.constant != "0" && !SupportsDefaultVectorsAndStrings()) {
return Error(
"Default values for strings and vectors are not supported in one "
"of the specified programming languages");
@@ -872,6 +1048,65 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
}
}
+ if (field->attributes.Lookup("vector64") != nullptr) {
+ if (!IsVector(type)) {
+ return Error("`vector64` attribute can only be applied on vectors.");
+ }
+
+ // Upgrade the type to be a BASE_TYPE_VECTOR64, since the attributes are
+ // parsed after the type.
+ const BaseType element_base_type = type.element;
+ type = Type(BASE_TYPE_VECTOR64, type.struct_def, type.enum_def);
+ type.element = element_base_type;
+
+ // Since the field was already added to the parent object, update the type
+ // in place.
+ field->value.type = type;
+
+ // 64-bit vectors imply the offset64 attribute.
+ field->offset64 = true;
+ }
+
+ // Record that this field uses 64-bit offsets.
+ if (field->attributes.Lookup("offset64") != nullptr) {
+ // TODO(derekbailey): would be nice to have this be a recommendation or hint
+ // instead of a warning.
+ if (type.base_type == BASE_TYPE_VECTOR64) {
+ Warning("attribute `vector64` implies `offset64` and isn't required.");
+ }
+
+ field->offset64 = true;
+ }
+
+ // Check for common conditions with Offset64 fields.
+ if (field->offset64) {
+ // TODO(derekbailey): this is where we can disable string support for
+ // offset64, as that is not a hard requirement to have.
+ if (!IsString(type) && !IsVector(type)) {
+ return Error(
+ "only string and vectors can have `offset64` attribute applied");
+ }
+
+ // If this is a Vector, only scalar and scalar-like (structs) items are
+ // allowed.
+ // TODO(derekbailey): allow vector of strings, just require that the strings
+ // are Offset64<string>.
+ if (IsVector(type) &&
+ !((IsScalar(type.element) && !IsEnum(type.VectorType())) ||
+ IsStruct(type.VectorType()))) {
+ return Error("only vectors of scalars are allowed to be 64-bit.");
+ }
+
+ // Lastly, check if it is supported by the specified generated languages. Do
+ // this last so the above checks can inform the user of schema errors to fix
+ // first.
+ if (!Supports64BitOffsets()) {
+ return Error(
+ "fields using 64-bit offsets are not yet supported in at least one "
+ "of the specified programming languages.");
+ }
+ }
+
// For historical convenience reasons, string keys are assumed required.
// Scalars are kDefault unless otherwise specified.
// Nonscalars are kOptional unless required;
@@ -894,8 +1129,16 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
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");
+ auto is_valid =
+ IsScalar(type.base_type) || IsString(type) || IsStruct(type);
+ if (IsArray(type)) {
+ is_valid |=
+ IsScalar(type.VectorType().base_type) || IsStruct(type.VectorType());
+ }
+ if (!is_valid) {
+ return Error(
+ "'key' field must be string, scalar type or fixed size array of "
+ "scalars");
}
}
@@ -914,7 +1157,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
}
if (!SupportsOptionalScalars()) {
return Error(
- "Optional scalars are not yet supported in at least one the of "
+ "Optional scalars are not yet supported in at least one of "
"the specified programming languages.");
}
}
@@ -978,15 +1221,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
"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");
+ if (field->native_inline && !IsStruct(field->value.type) &&
+ !IsVectorOfStruct(field->value.type) &&
+ !IsVectorOfTable(field->value.type))
+ return Error(
+ "'native_inline' can only be defined on structs, vector of structs or "
+ "vector of tables");
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)
+ if (!IsVector(type.base_type) || 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
@@ -1055,7 +1302,7 @@ CheckedError Parser::ParseComma() {
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def,
- uoffset_t count, bool inside_vector) {
+ size_t count, bool inside_vector) {
switch (val.type.base_type) {
case BASE_TYPE_UNION: {
FLATBUFFERS_ASSERT(field);
@@ -1121,7 +1368,11 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
}
uint8_t enum_idx;
if (vector_of_union_types) {
- enum_idx = vector_of_union_types->Get(count);
+ if (vector_of_union_types->size() <= count)
+ return Error(
+ "union types vector smaller than union values vector for: " +
+ field->name);
+ enum_idx = vector_of_union_types->Get(static_cast<uoffset_t>(count));
} else {
ECHECK(atot(constant.c_str(), *this, &enum_idx));
}
@@ -1150,9 +1401,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
ECHECK(ParseString(val, field->shared));
break;
}
+ case BASE_TYPE_VECTOR64:
case BASE_TYPE_VECTOR: {
uoffset_t off;
- ECHECK(ParseVector(val.type.VectorType(), &off, field, parent_fieldn));
+ ECHECK(ParseVector(val.type, &off, field, parent_fieldn));
val.constant = NumToString(off);
break;
}
@@ -1324,6 +1576,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
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.
+ // TODO(derekbailey): this doesn't work when there are Offset64 fields, as
+ // those have to be built first. So this needs to be changed to iterate over
+ // Offset64 then Offset32 fields.
for (auto it = field_stack_.rbegin();
it != field_stack_.rbegin() + fieldn_outer; ++it) {
auto &field_value = it->first;
@@ -1340,10 +1595,18 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
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); \
+ if (field->IsScalarOptional()) { \
+ if (field_value.constant != "null") { \
+ CTYPE val; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ builder_.AddElement(field_value.offset, 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)
@@ -1354,9 +1617,16 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
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); \
+ /* Special case for fields that use 64-bit addressing */ \
+ if(field->offset64) { \
+ Offset64<void> offset; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &offset)); \
+ builder_.AddOffset(field_value.offset, offset); \
+ } 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)
@@ -1394,7 +1664,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
}
template<typename F>
-CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
+CheckedError Parser::ParseVectorDelimiters(size_t &count, F body) {
EXPECT('[');
for (;;) {
if ((!opts.strict_json || !count) && Is(']')) break;
@@ -1407,91 +1677,6 @@ CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
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.
@@ -1509,10 +1694,11 @@ CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
NumToString(FLATBUFFERS_MAX_ALIGNMENT));
}
-CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
+CheckedError Parser::ParseVector(const Type &vector_type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn) {
- uoffset_t count = 0;
- auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ Type type = vector_type.VectorType();
+ size_t count = 0;
+ auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
Value val;
val.type = type;
ECHECK(ParseAnyValue(val, field, fieldn, nullptr, count, true));
@@ -1521,6 +1707,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
});
ECHECK(err);
+ const size_t alignment = InlineAlignment(type);
const size_t len = count * InlineSize(type) / InlineAlignment(type);
const size_t elemsize = InlineAlignment(type);
const auto force_align = field->attributes.Lookup("force_align");
@@ -1530,8 +1717,15 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
}
- builder_.StartVector(len, elemsize);
- for (uoffset_t i = 0; i < count; i++) {
+ // TODO Fix using element alignment as size (`elemsize`)!
+ if (vector_type.base_type == BASE_TYPE_VECTOR64) {
+ // TODO(derekbailey): this requires a 64-bit builder.
+ // builder_.StartVector<Offset64, uoffset64_t>(len, elemsize, alignment);
+ builder_.StartVector(len, elemsize, alignment);
+ } else {
+ builder_.StartVector(len, elemsize, alignment);
+ }
+ for (size_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) {
@@ -1553,7 +1747,11 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
}
builder_.ClearOffsets();
- *ovalue = builder_.EndVector(count);
+ if (vector_type.base_type == BASE_TYPE_VECTOR64) {
+ *ovalue = builder_.EndVector<uoffset64_t>(count);
+ } else {
+ *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.
@@ -1621,9 +1819,9 @@ CheckedError Parser::ParseArray(Value &array) {
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());
+ size_t count = 0;
+ auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
+ stack.emplace_back(Value());
auto &val = stack.back();
val.type = type;
if (IsStruct(type)) {
@@ -1667,7 +1865,13 @@ 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));
+ if (opts.json_nested_legacy_flatbuffers) {
+ ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def, 0));
+ } else {
+ return Error(
+ "cannot parse nested_flatbuffer as bytes unless"
+ " --json-nested-bytes is set");
+ }
} else {
auto cursor_at_value_begin = cursor_;
ECHECK(SkipAnyJsonValue());
@@ -1812,22 +2016,6 @@ 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());
@@ -1836,8 +2024,8 @@ CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
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] +
+ TypeName(BASE_TYPE_DOUBLE) +
+ ", found: " + TypeName(e.type.base_type) +
", name: " + (name ? *name : "") + ", value: " + e.constant);
}
NEXT();
@@ -1883,8 +2071,7 @@ CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
e.type.base_type = req;
} else {
return Error(std::string("type mismatch: expecting: ") +
- kTypeNames[e.type.base_type] +
- ", found: " + kTypeNames[req] +
+ TypeName(e.type.base_type) + ", found: " + TypeName(req) +
", name: " + (name ? *name : "") + ", value: " + e.constant);
}
}
@@ -1945,7 +2132,7 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
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 : "") +
+ TypeName(in_type) + ", name: " + (name ? *name : "") +
", value: " + attribute_);
}
@@ -2017,7 +2204,7 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
if (!match) {
std::string msg;
msg += "Cannot assign token starting with '" + TokenToStringId(token_) +
- "' to value of <" + std::string(kTypeNames[in_type]) + "> type.";
+ "' to value of <" + std::string(TypeName(in_type)) + "> type.";
return Error(msg);
}
const auto match_type = e.type.base_type; // may differ from in_type
@@ -2099,13 +2286,6 @@ 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());
@@ -2148,10 +2328,14 @@ void EnumDef::SortByValue() {
auto &v = vals.vec;
if (IsUInt64())
std::sort(v.begin(), v.end(), [](const EnumVal *e1, const EnumVal *e2) {
+ if (e1->GetAsUInt64() == e2->GetAsUInt64()) {
+ return e1->name < e2->name;
+ }
return e1->GetAsUInt64() < e2->GetAsUInt64();
});
else
std::sort(v.begin(), v.end(), [](const EnumVal *e1, const EnumVal *e2) {
+ if (e1->GetAsInt64() == e2->GetAsInt64()) { return e1->name < e2->name; }
return e1->GetAsInt64() < e2->GetAsInt64();
});
}
@@ -2281,13 +2465,18 @@ struct EnumValBuilder {
bool user_value;
};
-CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
+CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest,
+ const char *filename) {
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));
+ if (filename != nullptr && !opts.project_root.empty()) {
+ enum_def->declaration_file =
+ &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+ }
enum_def->doc_comment = enum_comment;
if (!is_union && !opts.proto_mode) {
// Give specialized error message, since this type spec used to
@@ -2314,6 +2503,9 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
// todo: Convert to the Error in the future?
Warning("underlying type of bit_flags enum must be unsigned");
}
+ if (enum_def->attributes.Lookup("force_align")) {
+ return Error("`force_align` is not a valid attribute for Enums. ");
+ }
EnumValBuilder evb(*this, *enum_def);
EXPECT('{');
// A lot of code generatos expect that an enum is not-empty.
@@ -2360,14 +2552,17 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
EXPECT(kTokenIntegerConstant);
}
- ECHECK(evb.AcceptEnumerator());
-
if (opts.proto_mode && Is('[')) {
NEXT();
// ignore attributes on enums.
while (token_ != ']') NEXT();
NEXT();
+ } else {
+ // parse attributes in fbs schema
+ ECHECK(ParseMetaData(&ev.attributes));
}
+
+ ECHECK(evb.AcceptEnumerator());
}
if (!Is(opts.proto_mode ? ';' : ',')) break;
NEXT();
@@ -2407,14 +2602,18 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
}
if (dest) *dest = enum_def;
- types_.Add(current_namespace_->GetFullyQualifiedName(enum_def->name),
- new Type(BASE_TYPE_UNION, nullptr, enum_def));
+ const auto qualified_name =
+ current_namespace_->GetFullyQualifiedName(enum_def->name);
+ if (types_.Add(qualified_name, new Type(BASE_TYPE_UNION, nullptr, enum_def)))
+ return Error("datatype already exists: " + qualified_name);
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);
+ if (!struct_def.predecl)
+ return Error("datatype already exists: " +
+ current_namespace_->GetFullyQualifiedName(name));
struct_def.predecl = false;
struct_def.name = name;
struct_def.file = file_being_parsed_;
@@ -2446,11 +2645,20 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
return NoError();
}
+std::vector<IncludedFile> Parser::GetIncludedFiles() const {
+ const auto it = files_included_per_file_.find(file_being_parsed_);
+ if (it == files_included_per_file_.end()) { return {}; }
+
+ return { it->second.cbegin(), it->second.cend() };
+}
+
bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
- IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary;
+ IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary |
+ IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson |
+ IDLOptions::kNim;
unsigned long langs = opts.lang_to_generate;
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
}
@@ -2461,23 +2669,28 @@ bool Parser::SupportsOptionalScalars() const {
bool Parser::SupportsDefaultVectorsAndStrings() const {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
- IDLOptions::kRust | IDLOptions::kSwift;
+ IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim;
return !(opts.lang_to_generate & ~supported_langs);
}
bool Parser::SupportsAdvancedUnionFeatures() const {
- return opts.lang_to_generate != 0 &&
- (opts.lang_to_generate &
+ return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
- IDLOptions::kBinary | IDLOptions::kSwift)) == 0;
+ IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim |
+ IDLOptions::kJson)) == 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;
+ IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0;
+}
+
+bool Parser::Supports64BitOffsets() const {
+ return (opts.lang_to_generate &
+ ~(IDLOptions::kCpp | IDLOptions::kJson | IDLOptions::kBinary)) == 0;
}
Namespace *Parser::UniqueNamespace(Namespace *ns) {
@@ -2506,13 +2719,7 @@ std::string Parser::UnqualifiedName(const std::string &full_qualified_name) {
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() {
+CheckedError Parser::ParseDecl(const char *filename) {
std::vector<std::string> dc = doc_comment_;
bool fixed = IsIdent("struct");
if (!fixed && !IsIdent("table")) return Error("declaration expected");
@@ -2523,6 +2730,10 @@ CheckedError Parser::ParseDecl() {
ECHECK(StartStruct(name, &struct_def));
struct_def->doc_comment = dc;
struct_def->fixed = fixed;
+ if (filename && !opts.project_root.empty()) {
+ struct_def->declaration_file =
+ &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+ }
ECHECK(ParseMetaData(&struct_def->attributes));
struct_def->sortbysize =
struct_def->attributes.Lookup("original_order") == nullptr && !fixed;
@@ -2568,6 +2779,7 @@ CheckedError Parser::ParseDecl() {
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
@@ -2594,12 +2806,15 @@ CheckedError Parser::ParseDecl() {
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));
+ const auto qualified_name =
+ current_namespace_->GetFullyQualifiedName(struct_def->name);
+ if (types_.Add(qualified_name,
+ new Type(BASE_TYPE_STRUCT, struct_def, nullptr)))
+ return Error("datatype already exists: " + qualified_name);
return NoError();
}
-CheckedError Parser::ParseService() {
+CheckedError Parser::ParseService(const char *filename) {
std::vector<std::string> service_comment = doc_comment_;
NEXT();
auto service_name = attribute_;
@@ -2609,6 +2824,10 @@ CheckedError Parser::ParseService() {
service_def.file = file_being_parsed_;
service_def.doc_comment = service_comment;
service_def.defined_namespace = current_namespace_;
+ if (filename != nullptr && !opts.project_root.empty()) {
+ service_def.declaration_file =
+ &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+ }
if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name),
&service_def))
return Error("service already exists: " + service_name);
@@ -2724,7 +2943,7 @@ CheckedError Parser::ParseProtoDecl() {
} else if (IsIdent("enum")) {
// These are almost the same, just with different terminator:
EnumDef *enum_def;
- ECHECK(ParseEnum(false, &enum_def));
+ ECHECK(ParseEnum(false, &enum_def, nullptr));
if (Is(';')) NEXT();
// Temp: remove any duplicates, as .fbs files can't handle them.
enum_def->RemoveDuplicates();
@@ -2747,17 +2966,17 @@ CheckedError Parser::ParseProtoDecl() {
return NoError();
}
-CheckedError Parser::StartEnum(const std::string &enum_name, bool is_union,
+CheckedError Parser::StartEnum(const std::string &name, bool is_union,
EnumDef **dest) {
auto &enum_def = *new EnumDef();
- enum_def.name = enum_name;
+ enum_def.name = 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);
+ const auto qualified_name = current_namespace_->GetFullyQualifiedName(name);
+ if (enums_.Add(qualified_name, &enum_def))
+ return Error("enum already exists: " + qualified_name);
enum_def.underlying_type.base_type =
is_union ? BASE_TYPE_UTYPE : BASE_TYPE_INT;
enum_def.underlying_type.enum_def = &enum_def;
@@ -2784,9 +3003,43 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
ECHECK(ParseProtoOption());
EXPECT(';');
} else if (IsIdent("reserved")) { // Skip these.
+ /**
+ * Reserved proto ids can be comma seperated (e.g. 1,2,4,5;)
+ * or range based (e.g. 9 to 11;)
+ * or combination of them (e.g. 1,2,9 to 11,4,5;)
+ * It will be ended by a semicolon.
+ */
NEXT();
- while (!Is(';')) { NEXT(); } // A variety of formats, just skip.
+ bool range = false;
+ voffset_t from = 0;
+
+ while (!Is(';')) {
+ if (token_ == kTokenIntegerConstant) {
+ voffset_t attribute = 0;
+ bool done = StringToNumber(attribute_.c_str(), &attribute);
+ if (!done)
+ return Error("Protobuf has non positive number in reserved ids");
+
+ if (range) {
+ for (voffset_t id = from + 1; id <= attribute; id++)
+ struct_def->reserved_ids.push_back(id);
+
+ range = false;
+ } else {
+ struct_def->reserved_ids.push_back(attribute);
+ }
+
+ from = attribute;
+ }
+
+ if (attribute_ == "to") range = true;
+
+ NEXT();
+ } // A variety of formats, just skip.
+
NEXT();
+ } else if (IsIdent("map")) {
+ ECHECK(ParseProtoMapField(struct_def));
} else {
std::vector<std::string> field_comment = doc_comment_;
// Parse the qualifier.
@@ -2816,7 +3069,7 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
if (IsIdent("group") || oneof) {
if (!oneof) NEXT();
if (oneof && opts.proto_oneof_union) {
- auto name = MakeCamel(attribute_, true) + "Union";
+ auto name = ConvertCase(attribute_, Case::kUpperCamel) + "Union";
ECHECK(StartEnum(name, true, &oneof_union));
type = Type(BASE_TYPE_UNION, nullptr, oneof_union);
} else {
@@ -2841,11 +3094,13 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
}
std::string name = attribute_;
EXPECT(kTokenIdentifier);
+ std::string proto_field_id;
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('=');
+ proto_field_id = attribute_;
EXPECT(kTokenIntegerConstant);
}
FieldDef *field = nullptr;
@@ -2856,6 +3111,11 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
}
if (!field) ECHECK(AddField(*struct_def, name, type, &field));
field->doc_comment = field_comment;
+ if (!proto_field_id.empty() || oneof) {
+ auto val = new Value();
+ val->constant = proto_field_id;
+ field->attributes.Add("id", val);
+ }
if (!IsScalar(type.base_type) && required) {
field->presence = FieldDef::kRequired;
}
@@ -2871,7 +3131,11 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
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()) {
+ if (IsFloat(type.base_type) &&
+ (val == "inf" || val == "+inf" || val == "-inf")) {
+ // Prefer to be explicit with +inf.
+ field->value.constant = val == "inf" ? "+inf" : val;
+ } else if (IsScalar(type.base_type) && numeric == val.c_str()) {
field->value.constant = val;
} else if (val == "true") {
field->value.constant = val;
@@ -2917,6 +3181,47 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
return NoError();
}
+CheckedError Parser::ParseProtoMapField(StructDef *struct_def) {
+ NEXT();
+ EXPECT('<');
+ Type key_type;
+ ECHECK(ParseType(key_type));
+ EXPECT(',');
+ Type value_type;
+ ECHECK(ParseType(value_type));
+ EXPECT('>');
+ auto field_name = attribute_;
+ NEXT();
+ EXPECT('=');
+ std::string proto_field_id = attribute_;
+ EXPECT(kTokenIntegerConstant);
+ EXPECT(';');
+
+ auto entry_table_name = ConvertCase(field_name, Case::kUpperCamel) + "Entry";
+ StructDef *entry_table;
+ ECHECK(StartStruct(entry_table_name, &entry_table));
+ entry_table->has_key = true;
+ FieldDef *key_field;
+ ECHECK(AddField(*entry_table, "key", key_type, &key_field));
+ key_field->key = true;
+ FieldDef *value_field;
+ ECHECK(AddField(*entry_table, "value", value_type, &value_field));
+
+ Type field_type;
+ field_type.base_type = BASE_TYPE_VECTOR;
+ field_type.element = BASE_TYPE_STRUCT;
+ field_type.struct_def = entry_table;
+ FieldDef *field;
+ ECHECK(AddField(*struct_def, field_name, field_type, &field));
+ if (!proto_field_id.empty()) {
+ auto val = new Value();
+ val->constant = proto_field_id;
+ field->attributes.Add("id", val);
+ }
+
+ return NoError();
+}
+
CheckedError Parser::ParseProtoKey() {
if (token_ == '(') {
NEXT();
@@ -3010,16 +3315,16 @@ CheckedError Parser::SkipAnyJsonValue() {
});
}
case '[': {
- uoffset_t count = 0;
- return ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
- return SkipAnyJsonValue();
- });
+ size_t count = 0;
+ return ParseVectorDelimiters(
+ count, [&](size_t &) -> CheckedError { return SkipAnyJsonValue(); });
}
case kTokenStringConstant:
case kTokenIntegerConstant:
case kTokenFloatConstant: NEXT(); break;
default:
- if (IsIdent("true") || IsIdent("false") || IsIdent("null")) {
+ if (IsIdent("true") || IsIdent("false") || IsIdent("null") ||
+ IsIdent("inf")) {
NEXT();
} else
return TokenError();
@@ -3061,8 +3366,8 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
}
case '[': {
auto start = builder->StartVector();
- uoffset_t count = 0;
- ECHECK(ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ size_t count = 0;
+ ECHECK(ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
return ParseFlexBufferValue(builder);
}));
builder->EndVector(start, false, false);
@@ -3150,6 +3455,10 @@ bool Parser::ParseJson(const char *json, const char *json_filename) {
return done;
}
+std::ptrdiff_t Parser::BytesConsumed() const {
+ return std::distance(source_, prev_cursor_);
+}
+
CheckedError Parser::StartParseFile(const char *source,
const char *source_filename) {
file_being_parsed_ = source_filename ? source_filename : "";
@@ -3232,30 +3541,76 @@ CheckedError Parser::ParseRoot(const char *source, const char **include_paths,
for (auto val_it = enum_def.Vals().begin();
val_it != enum_def.Vals().end(); ++val_it) {
auto &val = **val_it;
- if (!SupportsAdvancedUnionFeatures() &&
+
+ if (!(opts.lang_to_generate != 0 && SupportsAdvancedUnionFeatures()) &&
(IsStruct(val.union_type) || IsString(val.union_type)))
+
return Error(
"only tables can be union elements in the generated language: " +
val.name);
}
}
}
+
+ auto err = CheckPrivateLeak();
+ if (err.Check()) return err;
+
// 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);
+CheckedError Parser::CheckPrivateLeak() {
+ if (!opts.no_leak_private_annotations) return NoError();
+ // Iterate over all structs/tables to validate we arent leaking
+ // any private (structs/tables/enums)
+ for (auto it = structs_.vec.begin(); it != structs_.vec.end(); it++) {
+ auto &struct_def = **it;
+ for (auto fld_it = struct_def.fields.vec.begin();
+ fld_it != struct_def.fields.vec.end(); ++fld_it) {
+ auto &field = **fld_it;
+
+ if (field.value.type.enum_def) {
+ auto err =
+ CheckPrivatelyLeakedFields(struct_def, *field.value.type.enum_def);
+ if (err.Check()) { return err; }
+ } else if (field.value.type.struct_def) {
+ auto err = CheckPrivatelyLeakedFields(struct_def,
+ *field.value.type.struct_def);
+ if (err.Check()) { return err; }
+ }
+ }
+ }
+ // Iterate over all enums to validate we arent leaking
+ // any private (structs/tables)
+ 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 (val.union_type.struct_def) {
+ auto err =
+ CheckPrivatelyLeakedFields(enum_def, *val.union_type.struct_def);
+ if (err.Check()) { return err; }
+ }
+ }
+ }
+ }
+ return NoError();
+}
- return hash;
+CheckedError Parser::CheckPrivatelyLeakedFields(const Definition &def,
+ const Definition &value_type) {
+ if (!opts.no_leak_private_annotations) return NoError();
+ const auto is_private = def.attributes.Lookup("private");
+ const auto is_field_private = value_type.attributes.Lookup("private");
+ if (!is_private && is_field_private) {
+ return Error(
+ "Leaking private implementation, verify all objects have similar "
+ "annotations");
+ }
+ return NoError();
}
CheckedError Parser::DoParse(const char *source, const char **include_paths,
@@ -3272,7 +3627,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
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>();
+ files_included_per_file_[source_filename] = std::set<IncludedFile>();
} else {
return NoError();
}
@@ -3296,7 +3651,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
ECHECK(ParseProtoDecl());
} else if (IsIdent("native_include")) {
NEXT();
- vector_emplace_back(&native_included_files_, attribute_);
+ native_included_files_.emplace_back(attribute_);
EXPECT(kTokenStringConstant);
EXPECT(';');
} else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) {
@@ -3320,8 +3675,12 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
}
if (filepath.empty())
return Error("unable to locate include file: " + name);
- if (source_filename)
- files_included_per_file_[source_filename].insert(filepath);
+ if (source_filename) {
+ IncludedFile included_file;
+ included_file.filename = filepath;
+ included_file.schema_name = name;
+ files_included_per_file_[source_filename].insert(included_file);
+ }
std::string contents;
bool file_loaded = LoadFile(filepath.c_str(), true, &contents);
@@ -3364,9 +3723,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
} else if (token_ == '{') {
return NoError();
} else if (IsIdent("enum")) {
- ECHECK(ParseEnum(false, nullptr));
+ ECHECK(ParseEnum(false, nullptr, source_filename));
} else if (IsIdent("union")) {
- ECHECK(ParseEnum(true, nullptr));
+ ECHECK(ParseEnum(true, nullptr, source_filename));
} else if (IsIdent("root_type")) {
NEXT();
auto root_type = attribute_;
@@ -3382,9 +3741,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
NEXT();
file_identifier_ = attribute_;
EXPECT(kTokenStringConstant);
- if (file_identifier_.length() != FlatBufferBuilder::kFileIdentifierLength)
+ if (file_identifier_.length() != flatbuffers::kFileIdentifierLength)
return Error("file_identifier must be exactly " +
- NumToString(FlatBufferBuilder::kFileIdentifierLength) +
+ NumToString(flatbuffers::kFileIdentifierLength) +
" characters");
EXPECT(';');
} else if (IsIdent("file_extension")) {
@@ -3405,11 +3764,15 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
EXPECT(';');
known_attributes_[name] = false;
} else if (IsIdent("rpc_service")) {
- ECHECK(ParseService());
+ ECHECK(ParseService(source_filename));
} else {
- ECHECK(ParseDecl());
+ ECHECK(ParseDecl(source_filename));
}
}
+ EXPECT(kTokenEof);
+ if (opts.warnings_as_errors && has_warning_) {
+ return Error("treating warnings as errors, failed due to above warnings");
+ }
return NoError();
}
@@ -3433,9 +3796,11 @@ CheckedError Parser::DoParseJson() {
: nullptr);
}
}
- // Check that JSON file doesn't contain more objects or IDL directives.
- // Comments after JSON are allowed.
- EXPECT(kTokenEof);
+ if (opts.require_json_eof) {
+ // Check that JSON file doesn't contain more objects or IDL directives.
+ // Comments after JSON are allowed.
+ EXPECT(kTokenEof);
+ }
return NoError();
}
@@ -3454,11 +3819,11 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
// Workaround the lack of const accessor in C++98 maps.
auto &new_files =
- (*const_cast<std::map<std::string, std::set<std::string>> *>(
+ (*const_cast<std::map<std::string, std::set<IncludedFile>> *>(
&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);
+ if (included_files.find(it->filename) == included_files.end())
+ to_process.push_back(it->filename);
}
}
@@ -3467,16 +3832,42 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
// 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);
+static flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+SerializeAttributesCommon(const SymbolTable<Value> &attributes,
+ FlatBufferBuilder *builder, const Parser &parser) {
+ 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;
+ }
}
-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;
+static bool DeserializeAttributesCommon(
+ SymbolTable<Value> &attributes, 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;
}
void Parser::Serialize() {
@@ -3484,32 +3875,63 @@ void Parser::Serialize() {
AssignIndices(structs_.vec);
AssignIndices(enums_.vec);
std::vector<Offset<reflection::Object>> object_offsets;
+ std::set<std::string> files;
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;
+ const std::string *file = (*it)->declaration_file;
+ if (file) files.insert(*file);
}
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;
+ const std::string *file = (*it)->declaration_file;
+ if (file) files.insert(*file);
}
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;
+ const std::string *file = (*it)->declaration_file;
+ if (file) files.insert(*file);
+ }
+
+ // Create Schemafiles vector of tables.
+ flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::SchemaFile>>>
+ schema_files__;
+ if (!opts.project_root.empty()) {
+ std::vector<Offset<reflection::SchemaFile>> schema_files;
+ std::vector<Offset<flatbuffers::String>> included_files;
+ for (auto f = files_included_per_file_.begin();
+ f != files_included_per_file_.end(); f++) {
+ const auto filename__ = builder_.CreateSharedString(
+ RelativeToRootPath(opts.project_root, f->first));
+ for (auto i = f->second.begin(); i != f->second.end(); i++) {
+ included_files.push_back(builder_.CreateSharedString(
+ RelativeToRootPath(opts.project_root, i->filename)));
+ }
+ const auto included_files__ = builder_.CreateVector(included_files);
+ included_files.clear();
+
+ schema_files.push_back(
+ reflection::CreateSchemaFile(builder_, filename__, included_files__));
+ }
+ schema_files__ = builder_.CreateVectorOfSortedTables(&schema_files);
}
- 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(
+
+ const auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets);
+ const auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets);
+ const auto fiid__ = builder_.CreateString(file_identifier_);
+ const auto fext__ = builder_.CreateString(file_extension_);
+ const auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
+ const 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_));
+ static_cast<reflection::AdvancedFeatures>(advanced_features_),
+ schema_files__);
if (opts.size_prefixed) {
builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
} else {
@@ -3517,32 +3939,6 @@ void Parser::Serialize() {
}
}
-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;
@@ -3550,16 +3946,18 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
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__);
+ const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ const auto name__ = builder->CreateString(qualified_name);
+ const auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
+ const auto attr__ = SerializeAttributes(builder, parser);
+ const auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ std::string decl_file_in_project = declaration_file ? *declaration_file : "";
+ const auto file__ = builder->CreateSharedString(decl_file_in_project);
+ return reflection::CreateObject(
+ *builder, name__, flds__, fixed, static_cast<int>(minalign),
+ static_cast<int>(bytesize), attr__, docs__, file__);
}
bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
@@ -3580,6 +3978,14 @@ bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
delete field_def;
return false;
}
+ if (field_def->key) {
+ if (has_key) {
+ // only one field may be set as key
+ delete field_def;
+ return false;
+ }
+ has_key = true;
+ }
if (fixed) {
// Recompute padding since that's currently not serialized.
auto size = InlineSize(field_def->value.type);
@@ -3602,7 +4008,7 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
auto name__ = builder->CreateString(name);
auto type__ = value.type.Serialize(builder);
auto attr__ = SerializeAttributes(builder, parser);
- auto docs__ = parser.opts.binary_schema_comments
+ auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
? builder->CreateVectorOfStrings(doc_comment)
: 0;
double d;
@@ -3613,7 +4019,7 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
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());
+ attr__, docs__, IsOptional(), static_cast<uint16_t>(padding), offset64);
// 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.
}
@@ -3626,10 +4032,12 @@ bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
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);
+ value.constant = FloatToString(field->default_real(), 17);
}
presence = FieldDef::MakeFieldPresence(field->optional(), field->required());
+ padding = field->padding();
key = field->key();
+ offset64 = field->offset64();
if (!DeserializeAttributes(parser, field->attributes())) return false;
// TODO: this should probably be handled by a separate attribute
if (attributes.Lookup("flexbuffer")) {
@@ -3654,7 +4062,7 @@ 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
+ auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
? builder->CreateVectorOfStrings(doc_comment)
: 0;
return reflection::CreateRPCCall(
@@ -3678,14 +4086,17 @@ Offset<reflection::Service> ServiceDef::Serialize(FlatBufferBuilder *builder,
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__);
+ const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ const auto name__ = builder->CreateString(qualified_name);
+ const auto call__ = builder->CreateVector(servicecall_offsets);
+ const auto attr__ = SerializeAttributes(builder, parser);
+ const auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ std::string decl_file_in_project = declaration_file ? *declaration_file : "";
+ const auto file__ = builder->CreateSharedString(decl_file_in_project);
+ return reflection::CreateService(*builder, name__, call__, attr__, docs__,
+ file__);
}
bool ServiceDef::Deserialize(Parser &parser,
@@ -3712,16 +4123,18 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
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;
+ const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ const auto name__ = builder->CreateString(qualified_name);
+ const auto vals__ = builder->CreateVector(enumval_offsets);
+ const auto type__ = underlying_type.Serialize(builder);
+ const auto attr__ = SerializeAttributes(builder, parser);
+ const auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ std::string decl_file_in_project = declaration_file ? *declaration_file : "";
+ const auto file__ = builder->CreateSharedString(decl_file_in_project);
return reflection::CreateEnum(*builder, name__, vals__, is_union, type__,
- attr__, docs__);
+ attr__, docs__, file__);
}
bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) {
@@ -3743,34 +4156,52 @@ bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) {
return true;
}
+flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+EnumVal::SerializeAttributes(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ return SerializeAttributesCommon(attributes, builder, parser);
+}
+
+bool EnumVal::DeserializeAttributes(
+ Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
+ return DeserializeAttributesCommon(attributes, parser, attrs);
+}
+
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__);
+ const auto name__ = builder->CreateString(name);
+ const auto type__ = union_type.Serialize(builder);
+ const auto attr__ = SerializeAttributes(builder, parser);
+ const auto docs__ = parser.opts.binary_schema_comments && !doc_comment.empty()
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateEnumVal(*builder, name__, value, type__, docs__,
+ attr__);
}
-bool EnumVal::Deserialize(const Parser &parser,
- const reflection::EnumVal *val) {
+bool EnumVal::Deserialize(Parser &parser, const reflection::EnumVal *val) {
name = val->name()->str();
value = val->value();
if (!union_type.Deserialize(parser, val->union_type())) return false;
+ if (!DeserializeAttributes(parser, val->attributes())) return false;
DeserializeDoc(doc_comment, val->documentation());
return true;
}
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
+ size_t element_size = SizeOf(element);
+ if (base_type == BASE_TYPE_VECTOR && element == BASE_TYPE_STRUCT &&
+ struct_def->bytesize != 0) {
+ // struct_def->bytesize==0 means struct is table
+ element_size = struct_def->bytesize;
+ }
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);
+ fixed_length, static_cast<uint32_t>(SizeOf(base_type)),
+ static_cast<uint32_t>(element_size));
}
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
@@ -3804,37 +4235,12 @@ 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;
- }
+ return SerializeAttributesCommon(attributes, builder, parser);
}
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;
+ return DeserializeAttributesCommon(attributes, parser, attrs);
}
/************************************************************************/
@@ -3927,6 +4333,18 @@ bool Parser::Deserialize(const reflection::Schema *schema) {
}
}
advanced_features_ = schema->advanced_features();
+
+ if (schema->fbs_files())
+ for (auto s = schema->fbs_files()->begin(); s != schema->fbs_files()->end();
+ ++s) {
+ for (auto f = s->included_filenames()->begin();
+ f != s->included_filenames()->end(); ++f) {
+ IncludedFile included_file;
+ included_file.filename = f->str();
+ files_included_per_file_[s->filename()->str()].insert(included_file);
+ }
+ }
+
return true;
}
@@ -3937,17 +4355,25 @@ std::string Parser::ConformTo(const Parser &base) {
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
auto struct_def_base = base.LookupStruct(qualified_name);
if (!struct_def_base) continue;
+ std::set<FieldDef *> renamed_fields;
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);
+ const auto qualified_field_name = qualified_name + "." + 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;
+ if (field.value.offset != field_base->value.offset) {
+ return "offsets differ for field: " + qualified_field_name;
+ }
+ if (field.value.constant != field_base->value.constant) {
+ return "defaults differ for field: " + qualified_field_name;
+ }
+ if (!EqualByName(field.value.type, field_base->value.type)) {
+ return "types differ for field: " + qualified_field_name;
+ }
+ if (field.offset64 != field_base->offset64) {
+ return "offset types differ for field: " + qualified_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
@@ -3956,14 +4382,33 @@ std::string Parser::ConformTo(const Parser &base) {
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;
+ renamed_fields.insert(field_base);
+ if (!EqualByName(field.value.type, field_base->value.type)) {
+ const auto qualified_field_base =
+ qualified_name + "." + field_base->name;
+ return "field renamed to different type: " +
+ qualified_field_name + " (renamed from " +
+ qualified_field_base + ")";
+ }
break;
}
}
}
}
+ // deletion of trailing fields are not allowed
+ for (auto fit = struct_def_base->fields.vec.begin();
+ fit != struct_def_base->fields.vec.end(); ++fit) {
+ auto &field_base = **fit;
+ // not a renamed field
+ if (renamed_fields.find(&field_base) == renamed_fields.end()) {
+ auto field = struct_def.fields.Lookup(field_base.name);
+ if (!field) {
+ return "field deleted: " + qualified_name + "." + field_base.name;
+ }
+ }
+ }
}
+
for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) {
auto &enum_def = **eit;
auto qualified_name =
diff --git a/contrib/libs/flatbuffers/src/namer.h b/contrib/libs/flatbuffers/src/namer.h
new file mode 100644
index 0000000000..6a7fadcd14
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/namer.h
@@ -0,0 +1,266 @@
+#ifndef FLATBUFFERS_NAMER
+#define FLATBUFFERS_NAMER
+
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+// Options for Namer::File.
+enum class SkipFile {
+ None = 0,
+ Suffix = 1,
+ Extension = 2,
+ SuffixAndExtension = 3,
+};
+inline SkipFile operator&(SkipFile a, SkipFile b) {
+ return static_cast<SkipFile>(static_cast<int>(a) & static_cast<int>(b));
+}
+// Options for Namer::Directories
+enum class SkipDir {
+ None = 0,
+ // Skip prefixing the -o $output_path.
+ OutputPath = 1,
+ // Skip trailing path seperator.
+ TrailingPathSeperator = 2,
+ OutputPathAndTrailingPathSeparator = 3,
+};
+inline SkipDir operator&(SkipDir a, SkipDir b) {
+ return static_cast<SkipDir>(static_cast<int>(a) & static_cast<int>(b));
+}
+
+// `Namer` applies style configuration to symbols in generated code. It manages
+// casing, escapes keywords, and object API naming.
+// TODO: Refactor all code generators to use this.
+class Namer {
+ public:
+ struct Config {
+ // Symbols in code.
+
+ // Case style for flatbuffers-defined types.
+ // e.g. `class TableA {}`
+ Case types;
+ // Case style for flatbuffers-defined constants.
+ // e.g. `uint64_t ENUM_A_MAX`;
+ Case constants;
+ // Case style for flatbuffers-defined methods.
+ // e.g. `class TableA { int field_a(); }`
+ Case methods;
+ // Case style for flatbuffers-defined functions.
+ // e.g. `TableA* get_table_a_root()`;
+ Case functions;
+ // Case style for flatbuffers-defined fields.
+ // e.g. `struct Struct { int my_field; }`
+ Case fields;
+ // Case style for flatbuffers-defined variables.
+ // e.g. `int my_variable = 2`
+ Case variables;
+ // Case style for flatbuffers-defined variants.
+ // e.g. `enum class Enum { MyVariant, }`
+ Case variants;
+ // Seperator for qualified enum names.
+ // e.g. `Enum::MyVariant` uses `::`.
+ std::string enum_variant_seperator;
+
+ // Configures, when formatting code, whether symbols are checked against
+ // keywords and escaped before or after case conversion. It does not make
+ // sense to do so before, but its legacy behavior. :shrug:
+ // TODO(caspern): Deprecate.
+ enum class Escape {
+ BeforeConvertingCase,
+ AfterConvertingCase,
+ };
+ Escape escape_keywords;
+
+ // Namespaces
+
+ // e.g. `namespace my_namespace {}`
+ Case namespaces;
+ // The seperator between namespaces in a namespace path.
+ std::string namespace_seperator;
+
+ // Object API.
+ // Native versions flatbuffers types have this prefix.
+ // e.g. "" (it's usually empty string)
+ std::string object_prefix;
+ // Native versions flatbuffers types have this suffix.
+ // e.g. "T"
+ std::string object_suffix;
+
+ // Keywords.
+ // Prefix used to escape keywords. It is usually empty string.
+ std::string keyword_prefix;
+ // Suffix used to escape keywords. It is usually "_".
+ std::string keyword_suffix;
+
+ // Files.
+
+ // Case style for filenames. e.g. `foo_bar_generated.rs`
+ Case filenames;
+ // Case style for directories, e.g. `output_files/foo_bar/baz/`
+ Case directories;
+ // The directory within which we will generate files.
+ std::string output_path;
+ // Suffix for generated file names, e.g. "_generated".
+ std::string filename_suffix;
+ // Extension for generated files, e.g. ".cpp" or ".rs".
+ std::string filename_extension;
+ };
+ Namer(Config config, std::set<std::string> keywords)
+ : config_(config), keywords_(std::move(keywords)) {}
+
+ virtual ~Namer() {}
+
+ template<typename T> std::string Method(const T &s) const {
+ return Method(s.name);
+ }
+
+ virtual std::string Method(const std::string &pre,
+ const std::string &mid,
+ const std::string &suf) const {
+ return Format(pre + "_" + mid + "_" + suf, config_.methods);
+ }
+ virtual std::string Method(const std::string &pre,
+ const std::string &suf) const {
+ return Format(pre + "_" + suf, config_.methods);
+ }
+ virtual std::string Method(const std::string &s) const {
+ return Format(s, config_.methods);
+ }
+
+ virtual std::string Constant(const std::string &s) const {
+ return Format(s, config_.constants);
+ }
+
+ virtual std::string Function(const std::string &s) const {
+ return Format(s, config_.functions);
+ }
+
+ virtual std::string Variable(const std::string &s) const {
+ return Format(s, config_.variables);
+ }
+
+ template<typename T>
+ std::string Variable(const std::string &p, const T &s) const {
+ return Format(p + "_" + s.name, config_.variables);
+ }
+ virtual std::string Variable(const std::string &p,
+ const std::string &s) const {
+ return Format(p + "_" + s, config_.variables);
+ }
+
+ virtual std::string Namespace(const std::string &s) const {
+ return Format(s, config_.namespaces);
+ }
+
+ virtual std::string Namespace(const std::vector<std::string> &ns) const {
+ std::string result;
+ for (auto it = ns.begin(); it != ns.end(); it++) {
+ if (it != ns.begin()) result += config_.namespace_seperator;
+ result += Namespace(*it);
+ }
+ return result;
+ }
+
+ virtual std::string NamespacedType(const std::vector<std::string> &ns,
+ const std::string &s) const {
+ return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) +
+ Type(s);
+ }
+
+ // Returns `filename` with the right casing, suffix, and extension.
+ virtual std::string File(const std::string &filename,
+ SkipFile skips = SkipFile::None) const {
+ const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None;
+ const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None;
+ return ConvertCase(filename, config_.filenames, Case::kUpperCamel) +
+ (skip_suffix ? "" : config_.filename_suffix) +
+ (skip_ext ? "" : config_.filename_extension);
+ }
+ template<typename T>
+ std::string File(const T &f, SkipFile skips = SkipFile::None) const {
+ return File(f.name, skips);
+ }
+
+ // Formats `directories` prefixed with the output_path and joined with the
+ // right seperator. Output path prefixing and the trailing separator may be
+ // skiped using `skips`.
+ // Callers may want to use `EnsureDirExists` with the result.
+ virtual std::string Directories(const std::vector<std::string> &directories,
+ SkipDir skips = SkipDir::None) const {
+ const bool skip_output_path =
+ (skips & SkipDir::OutputPath) != SkipDir::None;
+ const bool skip_trailing_seperator =
+ (skips & SkipDir::TrailingPathSeperator) != SkipDir::None;
+ std::string result = skip_output_path ? "" : config_.output_path;
+ for (auto d = directories.begin(); d != directories.end(); d++) {
+ result += ConvertCase(*d, config_.directories, Case::kUpperCamel);
+ result.push_back(kPathSeparator);
+ }
+ if (skip_trailing_seperator && !result.empty()) result.pop_back();
+ return result;
+ }
+
+ virtual std::string EscapeKeyword(const std::string &name) const {
+ if (keywords_.find(name) == keywords_.end()) {
+ return name;
+ } else {
+ return config_.keyword_prefix + name + config_.keyword_suffix;
+ }
+ }
+
+ virtual std::string Type(const std::string &s) const {
+ return Format(s, config_.types);
+ }
+ virtual std::string Type(const std::string &t, const std::string &s) const {
+ return Format(t + "_" + s, config_.types);
+ }
+
+ virtual std::string ObjectType(const std::string &s) const {
+ return config_.object_prefix + Type(s) + config_.object_suffix;
+ }
+
+ virtual std::string Field(const std::string &s) const {
+ return Format(s, config_.fields);
+ }
+
+ virtual std::string Variant(const std::string &s) const {
+ return Format(s, config_.variants);
+ }
+
+ virtual std::string Format(const std::string &s, Case casing) const {
+ if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) {
+ return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel);
+ } else {
+ return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel));
+ }
+ }
+
+ // Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part
+ // after the `delimiter` (Fox) and placing the rest in `namespace_prefix`
+ // (The.Quick.Brown).
+ virtual std::string Denamespace(const std::string &s,
+ std::string &namespace_prefix,
+ const char delimiter = '.') const {
+ const size_t pos = s.find_last_of(delimiter);
+ if (pos == std::string::npos) {
+ namespace_prefix = "";
+ return s;
+ }
+ namespace_prefix = s.substr(0, pos);
+ return s.substr(pos + 1);
+ }
+
+ // Same as above, but disregards the prefix.
+ virtual std::string Denamespace(const std::string &s,
+ const char delimiter = '.') const {
+ std::string prefix;
+ return Denamespace(s, prefix, delimiter);
+ }
+
+ const Config config_;
+ const std::set<std::string> keywords_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_NAMER
diff --git a/contrib/libs/flatbuffers/src/reflection.cpp b/contrib/libs/flatbuffers/src/reflection.cpp
index 2dedcb4f18..0d0814ef62 100644
--- a/contrib/libs/flatbuffers/src/reflection.cpp
+++ b/contrib/libs/flatbuffers/src/reflection.cpp
@@ -22,8 +22,240 @@
namespace flatbuffers {
+namespace {
+
+static 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());
+}
+
+static 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.VerifyFieldStruct(reinterpret_cast<const uint8_t *>(&parent_table),
+ offset, obj.bytesize(), obj.minalign());
+}
+
+static 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
+static bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
+ const reflection::Object &obj,
+ const flatbuffers::Table *table, bool required);
+
+static 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;
+ }
+}
+
+static 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(), sizeof(uoffset_t)))
+ 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;
+ }
+}
+
+static 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(),
+ sizeof(uint8_t)))
+ return false;
+ break;
+ case reflection::Bool:
+ case reflection::Byte:
+ case reflection::UByte:
+ if (!table->VerifyField<int8_t>(v, field_def->offset(), sizeof(int8_t)))
+ return false;
+ break;
+ case reflection::Short:
+ case reflection::UShort:
+ if (!table->VerifyField<int16_t>(v, field_def->offset(),
+ sizeof(int16_t)))
+ return false;
+ break;
+ case reflection::Int:
+ case reflection::UInt:
+ if (!table->VerifyField<int32_t>(v, field_def->offset(),
+ sizeof(int32_t)))
+ return false;
+ break;
+ case reflection::Long:
+ case reflection::ULong:
+ if (!table->VerifyField<int64_t>(v, field_def->offset(),
+ sizeof(int64_t)))
+ return false;
+ break;
+ case reflection::Float:
+ if (!table->VerifyField<float>(v, field_def->offset(), sizeof(float)))
+ return false;
+ break;
+ case reflection::Double:
+ if (!table->VerifyField<double>(v, field_def->offset(), sizeof(double)))
+ return false;
+ break;
+ case reflection::String:
+ if (!table->VerifyField<uoffset_t>(v, field_def->offset(),
+ sizeof(uoffset_t)) ||
+ !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;
+}
+
+
+} // namespace
+
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
-// clang-format off
+ // clang-format off
#define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data))
switch (type) {
case reflection::UType:
@@ -120,8 +352,25 @@ std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
}
}
+void ForAllFields(const reflection::Object *object, bool reverse,
+ std::function<void(const reflection::Field *)> func) {
+ std::vector<uint32_t> field_to_id_map;
+ field_to_id_map.resize(object->fields()->size());
+
+ // Create the mapping of field ID to the index into the vector.
+ for (uint32_t i = 0; i < object->fields()->size(); ++i) {
+ auto field = object->fields()->Get(i);
+ field_to_id_map[field->id()] = i;
+ }
+
+ for (size_t i = 0; i < field_to_id_map.size(); ++i) {
+ func(object->fields()->Get(
+ field_to_id_map[reverse ? field_to_id_map.size() - i + 1 : i]));
+ }
+}
+
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
-// clang-format off
+ // clang-format off
#define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val))
switch (type) {
case reflection::UType:
@@ -180,7 +429,7 @@ class ResizeContext {
std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr)
: schema_(schema),
- startptr_(vector_data(*flatbuf) + start),
+ startptr_(flatbuf->data() + start),
delta_(delta),
buf_(*flatbuf),
dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
@@ -188,8 +437,8 @@ class ResizeContext {
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_));
+ auto root = GetAnyRoot(buf_.data());
+ Straddle<uoffset_t, 1>(buf_.data(), root, buf_.data());
ResizeTable(root_table ? *root_table : *schema.root_table(), root);
// We can now add or remove bytes at start.
if (delta_ > 0)
@@ -217,7 +466,7 @@ class ResizeContext {
// 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_));
+ reinterpret_cast<const uoffset_t *>(buf_.data());
return dag_check_[dag_idx];
}
@@ -257,7 +506,9 @@ class ResizeContext {
// Recurse.
switch (base_type) {
case reflection::Obj: {
- ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
+ if (subobjectdef) {
+ ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
+ }
break;
}
case reflection::Vector: {
@@ -309,19 +560,19 @@ void SetString(const reflection::Schema &schema, const std::string &val,
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));
+ reinterpret_cast<const uint8_t *>(str) - flatbuf->data());
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());
+ memset(flatbuf->data() + start, 0, str->size());
// Different size, we must expand (or contract).
- ResizeContext(schema, start, delta, flatbuf, root_table);
+ ResizeContext ctx(schema, start, delta, flatbuf, root_table);
// Set the new length.
- WriteScalar(vector_data(*flatbuf) + str_start,
+ WriteScalar(flatbuf->data() + 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);
+ memcpy(flatbuf->data() + start, val.c_str(), val.size() + 1);
}
uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
@@ -330,25 +581,26 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
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);
+ auto vec_start = reinterpret_cast<const uint8_t *>(vec) - flatbuf->data();
+ auto start = static_cast<uoffset_t>(vec_start) +
+ static_cast<uoffset_t>(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);
+ memset(flatbuf->data() + start - size_clear, 0, size_clear);
}
- ResizeContext(schema, start, delta_bytes, flatbuf, root_table);
- WriteScalar(vector_data(*flatbuf) + vec_start, newsize); // Length field.
+ ResizeContext ctx(schema, start, delta_bytes, flatbuf, root_table);
+ WriteScalar(flatbuf->data() + 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);
+ memset(flatbuf->data() + start, 0,
+ static_cast<size_t>(delta_elem) * elem_size);
}
}
- return vector_data(*flatbuf) + start;
+ return flatbuf->data() + start;
}
const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
@@ -363,15 +615,11 @@ const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
// 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;
+ return flatbuf.data() + 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,
@@ -443,9 +691,10 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
FLATBUFFERS_FALLTHROUGH(); // fall thru
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
+ auto element_alignment = element_size; // For primitive elements
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
- fbb.StartVector(vec->size(), element_size);
+ fbb.StartVector(vec->size(), element_size, element_alignment);
fbb.PushBytes(vec->Data(), element_size * vec->size());
offset = fbb.EndVector(vec->size());
break;
@@ -497,217 +746,22 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
}
}
-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 *const buf, const size_t length,
+ const uoffset_t max_depth, const uoffset_t max_tables) {
+ Verifier v(buf, length, max_depth, max_tables);
+ return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf),
+ /*required=*/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*/) {
+bool VerifySizePrefixed(const reflection::Schema &schema,
+ const reflection::Object &root,
+ const uint8_t *const buf, const size_t length,
+ const uoffset_t max_depth, const uoffset_t max_tables) {
Verifier v(buf, length, max_depth, max_tables);
- return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true);
+ return VerifyObject(v, schema, root, flatbuffers::GetAnySizePrefixedRoot(buf),
+ /*required=*/true);
}
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/util.cpp b/contrib/libs/flatbuffers/src/util.cpp
index 3670a01939..38d8536c09 100644
--- a/contrib/libs/flatbuffers/src/util.cpp
+++ b/contrib/libs/flatbuffers/src/util.cpp
@@ -17,13 +17,14 @@
// clang-format off
// Dont't remove `format off`, it prevent reordering of win-includes.
+#include <cstring>
#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) || \
defined(__QNXNTO__)
# define _POSIX_C_SOURCE 200809L
# define _XOPEN_SOURCE 700L
#endif
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
@@ -34,28 +35,35 @@
# include <crtdbg.h>
# endif
# include <windows.h> // Must be included before <direct.h>
-# include <direct.h>
+# ifndef __CYGWIN__
+# include <direct.h>
+# endif
# 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>
+#include <functional>
+
+#include "flatbuffers/base.h"
namespace flatbuffers {
-bool FileExistsRaw(const char *name) {
+namespace {
+
+static bool FileExistsRaw(const char *name) {
std::ifstream ifs(name);
return ifs.good();
}
-bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
+static 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;
@@ -75,8 +83,131 @@ bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
return !ifs.bad();
}
-static LoadFileFunction g_load_file_function = LoadFileRaw;
-static FileExistsFunction g_file_exists_function = FileExistsRaw;
+LoadFileFunction g_load_file_function = LoadFileRaw;
+FileExistsFunction g_file_exists_function = FileExistsRaw;
+
+static std::string ToCamelCase(const std::string &input, bool is_upper) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (!i && input[i] == '_') {
+ s += input[i];
+ // we ignore leading underscore but make following
+ // alphabet char upper.
+ if (i + 1 < input.length() && is_alpha(input[i + 1]))
+ s += CharToUpper(input[++i]);
+ }
+ else if (!i)
+ s += is_upper ? CharToUpper(input[i]) : CharToLower(input[i]);
+ else if (input[i] == '_' && i + 1 < input.length())
+ s += CharToUpper(input[++i]);
+ else
+ s += input[i];
+ }
+ return s;
+}
+
+static std::string ToSnakeCase(const std::string &input, bool screaming) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (i == 0) {
+ s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
+ } else if (input[i] == '_') {
+ s += '_';
+ } else if (!islower(input[i])) {
+ // Prevent duplicate underscores for Upper_Snake_Case strings
+ // and UPPERCASE strings.
+ if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
+ s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
+ } else {
+ s += screaming ? CharToUpper(input[i]) : input[i];
+ }
+ }
+ return s;
+}
+
+std::string ToAll(const std::string &input,
+ std::function<char(const char)> transform) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) { s += transform(input[i]); }
+ return s;
+}
+
+std::string CamelToSnake(const std::string &input) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (i == 0) {
+ s += CharToLower(input[i]);
+ } else if (input[i] == '_') {
+ s += '_';
+ } else if (!islower(input[i])) {
+ // Prevent duplicate underscores for Upper_Snake_Case strings
+ // and UPPERCASE strings.
+ if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
+ s += CharToLower(input[i]);
+ } else {
+ s += input[i];
+ }
+ }
+ return s;
+}
+
+std::string DasherToSnake(const std::string &input) {
+ std::string s;
+ for (size_t i = 0; i < input.length(); i++) {
+ if (input[i] == '-') {
+ s += "_";
+ } else {
+ s += input[i];
+ }
+ }
+ return s;
+}
+
+std::string ToDasher(const std::string &input) {
+ std::string s;
+ char p = 0;
+ for (size_t i = 0; i < input.length(); i++) {
+ char const &c = input[i];
+ if (c == '_') {
+ if (i > 0 && p != kPathSeparator &&
+ // The following is a special case to ignore digits after a _. This is
+ // because ThisExample3 would be converted to this_example_3 in the
+ // CamelToSnake conversion, and then dasher would do this-example-3,
+ // but it expects this-example3.
+ !(i + 1 < input.length() && isdigit(input[i + 1])))
+ s += "-";
+ } else {
+ s += c;
+ }
+ p = c;
+ }
+ return s;
+}
+
+
+// Converts foo_bar_123baz_456 to foo_bar123_baz456
+std::string SnakeToSnake2(const std::string &s) {
+ if (s.length() <= 1) return s;
+ std::string result;
+ result.reserve(s.size());
+ for (size_t i = 0; i < s.length() - 1; i++) {
+ if (s[i] == '_' && isdigit(s[i + 1])) {
+ continue; // Move the `_` until after the digits.
+ }
+
+ result.push_back(s[i]);
+
+ if (isdigit(s[i]) && isalpha(s[i + 1]) && islower(s[i + 1])) {
+ result.push_back('_');
+ }
+ }
+ result.push_back(s.back());
+
+ return result;
+}
+
+} // namespace
+
bool LoadFile(const char *name, bool binary, std::string *buf) {
FLATBUFFERS_ASSERT(g_load_file_function);
@@ -152,11 +283,20 @@ std::string StripFileName(const std::string &filepath) {
return i != std::string::npos ? filepath.substr(0, i) : "";
}
+std::string StripPrefix(const std::string &filepath,
+ const std::string &prefix_to_remove) {
+ if (!strncmp(filepath.c_str(), prefix_to_remove.c_str(),
+ prefix_to_remove.size())) {
+ return filepath.substr(prefix_to_remove.size());
+ }
+ return filepath;
+}
+
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);
+ char &filepath_last_character = filepath.back();
if (filepath_last_character == kPathSeparatorWindows) {
filepath_last_character = kPathSeparator;
} else if (filepath_last_character != kPathSeparator) {
@@ -176,6 +316,9 @@ std::string PosixPath(const char *path) {
std::replace(p.begin(), p.end(), '\\', '/');
return p;
}
+std::string PosixPath(const std::string &path) {
+ return PosixPath(path.c_str());
+}
void EnsureDirExists(const std::string &filepath) {
auto parent = StripFileName(filepath);
@@ -196,7 +339,7 @@ std::string AbsolutePath(const std::string &filepath) {
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
return filepath;
#else
- #ifdef _WIN32
+ #if defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__)
char abs_path[MAX_PATH];
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
#else
@@ -215,6 +358,36 @@ std::string AbsolutePath(const std::string &filepath) {
// clang-format on
}
+std::string RelativeToRootPath(const std::string &project,
+ const std::string &filepath) {
+ std::string absolute_project = PosixPath(AbsolutePath(project));
+ if (absolute_project.back() != '/') absolute_project += "/";
+ std::string absolute_filepath = PosixPath(AbsolutePath(filepath));
+
+ // Find the first character where they disagree.
+ // The previous directory is the lowest common ancestor;
+ const char *a = absolute_project.c_str();
+ const char *b = absolute_filepath.c_str();
+ size_t common_prefix_len = 0;
+ while (*a != '\0' && *b != '\0' && *a == *b) {
+ if (*a == '/') common_prefix_len = a - absolute_project.c_str();
+ a++;
+ b++;
+ }
+ // the number of ../ to prepend to b depends on the number of remaining
+ // directories in A.
+ const char *suffix = absolute_project.c_str() + common_prefix_len;
+ size_t num_up = 0;
+ while (*suffix != '\0')
+ if (*suffix++ == '/') num_up++;
+ num_up--; // last one is known to be '/'.
+ std::string result = "//";
+ for (size_t i = 0; i < num_up; i++) result += "../";
+ result += absolute_filepath.substr(common_prefix_len + 1);
+
+ return result;
+}
+
// Locale-independent code.
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && \
(FLATBUFFERS_LOCALE_INDEPENDENT > 0)
@@ -238,8 +411,7 @@ ClassicLocale ClassicLocale::instance_;
std::string RemoveStringQuotes(const std::string &s) {
auto ch = *s.c_str();
- return ((s.size() >= 2) && (ch == '\"' || ch == '\'') &&
- (ch == string_back(s)))
+ return ((s.size() >= 2) && (ch == '\"' || ch == '\'') && (ch == s.back()))
? s.substr(1, s.length() - 2)
: s;
}
@@ -261,27 +433,36 @@ bool ReadEnvironmentVariable(const char *var_name, std::string *_value) {
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
+std::string ConvertCase(const std::string &input, Case output_case,
+ Case input_case) {
+ if (output_case == Case::kKeep) return input;
+ // The output cases expect snake_case inputs, so if we don't have that input
+ // format, try to convert to snake_case.
+ switch (input_case) {
+ case Case::kLowerCamel:
+ case Case::kUpperCamel:
+ return ConvertCase(CamelToSnake(input), output_case);
+ case Case::kDasher: return ConvertCase(DasherToSnake(input), output_case);
+ case Case::kKeep: printf("WARNING: Converting from kKeep case.\n"); break;
+ default:
+ case Case::kSnake:
+ case Case::kScreamingSnake:
+ case Case::kAllLower:
+ case Case::kAllUpper: break;
+ }
- // clang-format on
+ switch (output_case) {
+ case Case::kUpperCamel: return ToCamelCase(input, true);
+ case Case::kLowerCamel: return ToCamelCase(input, false);
+ case Case::kSnake: return input;
+ case Case::kScreamingSnake: return ToSnakeCase(input, true);
+ case Case::kAllUpper: return ToAll(input, CharToUpper);
+ case Case::kAllLower: return ToAll(input, CharToLower);
+ case Case::kDasher: return ToDasher(input);
+ case Case::kSnake2: return SnakeToSnake2(input);
+ default:
+ case Case::kUnknown: return input;
+ }
}
} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/ya.make b/contrib/libs/flatbuffers/ya.make
index 0fa3e01129..6ef100077d 100644
--- a/contrib/libs/flatbuffers/ya.make
+++ b/contrib/libs/flatbuffers/ya.make
@@ -2,17 +2,18 @@
LIBRARY()
-VERSION(2.0.0)
+VERSION(23.5.9)
-ORIGINAL_SOURCE(https://github.com/google/flatbuffers/archive/v2.0.0.tar.gz)
+ORIGINAL_SOURCE(https://github.com/google/flatbuffers/archive/v23.5.9.tar.gz)
-LICENSE(
- Apache-2.0 AND
- BSD-3-Clause
-)
+LICENSE(Apache-2.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+PEERDIR(
+ contrib/restricted/abseil-cpp/absl/base
+)
+
ADDINCL(
contrib/libs/flatbuffers/include
)