aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/grpc/third_party
diff options
context:
space:
mode:
authorleonidlazarev <leonidlazarev@yandex-team.com>2023-06-02 15:07:38 +0300
committerleonidlazarev <leonidlazarev@yandex-team.com>2023-06-02 15:07:38 +0300
commit59e0045a61e61c2ac38878f2adc7ec91ca914cc1 (patch)
treeb6b64c51025630a7d40923d4aa7b7b882e1a8848 /contrib/libs/grpc/third_party
parent7506c5c295065b4360d617393af34203f037946d (diff)
downloadydb-59e0045a61e61c2ac38878f2adc7ec91ca914cc1.tar.gz
feat grpc: update to grpc 1.50.2
update grpc to 1.50.2 update grpcio to 1.50.0 Удаленные патчи: 06-flow_control.patch - логика в upstream удалена 10-fix-crash-on-fork.patch - логика в upstream удалена 12-coverity-fix.patch - логика в upstream удалена 20-P2166-string-nullptr.patch - в upstream временный объект вместо nullptr PR29209-fix-heap-use-after-free.patch - решение есть в upstream Добавленные патчи: pr33085_fix_epoll1_engine_reinit.patch 21-windows_build.patch
Diffstat (limited to 'contrib/libs/grpc/third_party')
-rw-r--r--contrib/libs/grpc/third_party/README.md9
-rw-r--r--contrib/libs/grpc/third_party/upb/CMakeLists.darwin-x86_64.txt8
-rw-r--r--contrib/libs/grpc/third_party/upb/CMakeLists.linux-aarch64.txt8
-rw-r--r--contrib/libs/grpc/third_party/upb/CMakeLists.linux-x86_64.txt8
-rw-r--r--contrib/libs/grpc/third_party/upb/CMakeLists.windows-x86_64.txt8
-rw-r--r--contrib/libs/grpc/third_party/upb/DESIGN.md4
-rw-r--r--contrib/libs/grpc/third_party/upb/README.md16
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/arena.c277
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/arena.h225
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/array.c114
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/array.h83
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode.c264
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode.h1
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode_fast.c2
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.c185
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.h24
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.hpp11
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/encode.c71
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/encode.h22
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/extension_registry.c93
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/extension_registry.h84
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/internal/decode.h (renamed from contrib/libs/grpc/third_party/upb/upb/decode_internal.h)10
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/internal/table.h (renamed from contrib/libs/grpc/third_party/upb/upb/table_internal.h)12
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/internal/upb.h (renamed from contrib/libs/grpc/third_party/upb/upb/upb_internal.h)6
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/internal/vsnprintf_compat.h52
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/json_decode.c1512
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/json_decode.h47
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/json_encode.c780
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/json_encode.h65
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/map.c108
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/map.h117
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/message_value.h66
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/mini_table.c1147
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/mini_table.h189
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/msg.c74
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/msg.h48
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/msg_internal.h135
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/port_def.inc11
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/port_undef.inc2
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/reflection.c161
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/reflection.h114
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/status.c86
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/status.h66
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/table.c20
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/text_encode.c5
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.c294
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.h175
47 files changed, 5715 insertions, 1104 deletions
diff --git a/contrib/libs/grpc/third_party/README.md b/contrib/libs/grpc/third_party/README.md
index 19ab6d424e..4425c05620 100644
--- a/contrib/libs/grpc/third_party/README.md
+++ b/contrib/libs/grpc/third_party/README.md
@@ -118,13 +118,18 @@ Apart from the above steps, please perform the following two steps to generate t
Since upb is vendored in the gRPC repo, you cannot use submodule to update it. Please follow the steps below.
1. Update third_party/upb directory by running
- `git subtree pull --squash --prefix=third_party/upb https://github.com/protocolbuffers/upb.git master`
+ - `export GRPC_ROOT=~/git/grpc`
+ - `wget https://github.com/protocolbuffers/upb/archive/refs/heads/main.zip`
+ - `rm -rf $GRPC_ROOT/third_party/upb`
+ - `unzip main.zip -d $GRPC_ROOT/third_party`
+ - `mv $GRPC_ROOT/third_party/upb-main $GRPC_ROOT/third_party/upb`
2. Update the dependency in `grpc_deps.bzl` to the same commit
3. Populate the bazel download mirror by running `bazel/update_mirror.sh`
4. Update `src/upb/gen_build_yaml.py` for newly added or removed upb files
+ - Running `bazel query "deps(upb) union deps(json) union deps(textformat)"`
+ under third_party/upb would give some idea on what needs to be included.
5. Run `tools/buildgen/generate_projects.sh` to regenerate the generated files
6. Run `tools/codegen/core/gen_upb_api.sh` to regenerate upb files.
- If you see breaking changes here, you may want to import upb into Google3 along with gRPC.
### Updating third_party/xxhash
diff --git a/contrib/libs/grpc/third_party/upb/CMakeLists.darwin-x86_64.txt b/contrib/libs/grpc/third_party/upb/CMakeLists.darwin-x86_64.txt
index 95e91287c1..f371cc9d39 100644
--- a/contrib/libs/grpc/third_party/upb/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/grpc/third_party/upb/CMakeLists.darwin-x86_64.txt
@@ -25,12 +25,20 @@ target_sources(grpc-third_party-upb PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/naive.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-neon.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-sse.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/arena.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/array.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/def.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_decode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/map.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/mini_table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/msg.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/reflection.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/status.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/text_encode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/upb.c
diff --git a/contrib/libs/grpc/third_party/upb/CMakeLists.linux-aarch64.txt b/contrib/libs/grpc/third_party/upb/CMakeLists.linux-aarch64.txt
index a0963907a3..2949b633aa 100644
--- a/contrib/libs/grpc/third_party/upb/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/grpc/third_party/upb/CMakeLists.linux-aarch64.txt
@@ -28,12 +28,20 @@ target_sources(grpc-third_party-upb PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/naive.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-neon.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-sse.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/arena.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/array.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/def.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_decode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/map.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/mini_table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/msg.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/reflection.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/status.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/text_encode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/upb.c
diff --git a/contrib/libs/grpc/third_party/upb/CMakeLists.linux-x86_64.txt b/contrib/libs/grpc/third_party/upb/CMakeLists.linux-x86_64.txt
index a0963907a3..2949b633aa 100644
--- a/contrib/libs/grpc/third_party/upb/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/grpc/third_party/upb/CMakeLists.linux-x86_64.txt
@@ -28,12 +28,20 @@ target_sources(grpc-third_party-upb PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/naive.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-neon.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-sse.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/arena.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/array.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/def.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_decode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/map.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/mini_table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/msg.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/reflection.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/status.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/text_encode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/upb.c
diff --git a/contrib/libs/grpc/third_party/upb/CMakeLists.windows-x86_64.txt b/contrib/libs/grpc/third_party/upb/CMakeLists.windows-x86_64.txt
index f9d6d5f4dd..0178cbffda 100644
--- a/contrib/libs/grpc/third_party/upb/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/grpc/third_party/upb/CMakeLists.windows-x86_64.txt
@@ -24,12 +24,20 @@ target_sources(grpc-third_party-upb PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/naive.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-neon.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/third_party/utf8_range/range2-sse.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/arena.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/array.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/def.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_decode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/json_encode.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/map.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/mini_table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/msg.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/reflection.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/status.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/table.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/text_encode.c
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/upb.c
diff --git a/contrib/libs/grpc/third_party/upb/DESIGN.md b/contrib/libs/grpc/third_party/upb/DESIGN.md
index 73388d037a..aa6a288280 100644
--- a/contrib/libs/grpc/third_party/upb/DESIGN.md
+++ b/contrib/libs/grpc/third_party/upb/DESIGN.md
@@ -68,7 +68,7 @@ typedef struct {
Note in particular that messages do *not* have:
- A pointer to reflection or a parse table (upb messages are not self-describing).
-- A pointer to an arena (the arena must be expicitly passed into any function that
+- A pointer to an arena (the arena must be explicitly passed into any function that
allocates).
The upb compiler computes a layout for each message, and determines the offset for
@@ -160,7 +160,7 @@ together.
together, their lifetimes are irreversibly joined, such that none of the arena
blocks in either arena will be freed until *both* arenas are freed with
`upb_arena_free()`. This is useful when joining two messages from separate
-arenas (making one a sub-message of the other). Fuse is an a very cheap
+arenas (making one a sub-message of the other). Fuse is a very cheap
operation, and an unlimited number of arenas can be fused together efficiently.
## Reflection and Descriptors
diff --git a/contrib/libs/grpc/third_party/upb/README.md b/contrib/libs/grpc/third_party/upb/README.md
index 92a081bbef..9b74b969ce 100644
--- a/contrib/libs/grpc/third_party/upb/README.md
+++ b/contrib/libs/grpc/third_party/upb/README.md
@@ -57,6 +57,22 @@ For PHP, use [PECL](https://pecl.php.net/package/protobuf):
$ sudo pecl install protobuf
```
+Alternatively, you can build and install upb using
+[vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:
+
+ git clone https://github.com/Microsoft/vcpkg.git
+ cd vcpkg
+ ./bootstrap-vcpkg.sh
+ ./vcpkg integrate install
+ ./vcpkg install upb
+
+The upb port in vcpkg is kept up to date by microsoft team members and community
+contributors.
+
+If the version is out of date, please
+[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
+vcpkg repository.
+
## Contributing
Please see [CONTRIBUTING.md](CONTRIBUTING.md).
diff --git a/contrib/libs/grpc/third_party/upb/upb/arena.c b/contrib/libs/grpc/third_party/upb/upb/arena.c
new file mode 100644
index 0000000000..3c872698cd
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/arena.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/arena.h"
+
+#include <stdlib.h>
+
+#include "upb/internal/upb.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+/* upb_alloc ******************************************************************/
+
+static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize,
+ size_t size) {
+ UPB_UNUSED(alloc);
+ UPB_UNUSED(oldsize);
+ if (size == 0) {
+ free(ptr);
+ return NULL;
+ } else {
+ return realloc(ptr, size);
+ }
+}
+
+static uint32_t* upb_cleanup_pointer(uintptr_t cleanup_metadata) {
+ return (uint32_t*)(cleanup_metadata & ~0x1);
+}
+
+static bool upb_cleanup_has_initial_block(uintptr_t cleanup_metadata) {
+ return cleanup_metadata & 0x1;
+}
+
+static uintptr_t upb_cleanup_metadata(uint32_t* cleanup,
+ bool has_initial_block) {
+ return (uintptr_t)cleanup | has_initial_block;
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+/* upb_Arena ******************************************************************/
+
+struct mem_block {
+ struct mem_block* next;
+ uint32_t size;
+ uint32_t cleanups;
+ /* Data follows. */
+};
+
+typedef struct cleanup_ent {
+ upb_CleanupFunc* cleanup;
+ void* ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve =
+ UPB_ALIGN_UP(sizeof(mem_block), UPB_MALLOC_ALIGN);
+
+static upb_Arena* arena_findroot(upb_Arena* a) {
+ /* Path splitting keeps time complexity down, see:
+ * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
+ while (a->parent != a) {
+ upb_Arena* next = a->parent;
+ a->parent = next->parent;
+ a = next;
+ }
+ return a;
+}
+
+static void upb_Arena_addblock(upb_Arena* a, upb_Arena* root, void* ptr,
+ size_t size) {
+ mem_block* block = ptr;
+
+ /* The block is for arena |a|, but should appear in the freelist of |root|. */
+ block->next = root->freelist;
+ block->size = (uint32_t)size;
+ block->cleanups = 0;
+ root->freelist = block;
+ a->last_size = block->size;
+ if (!root->freelist_tail) root->freelist_tail = block;
+
+ a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
+ a->head.end = UPB_PTR_AT(block, size, char);
+ a->cleanup_metadata = upb_cleanup_metadata(
+ &block->cleanups, upb_cleanup_has_initial_block(a->cleanup_metadata));
+
+ UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
+}
+
+static bool upb_Arena_Allocblock(upb_Arena* a, size_t size) {
+ upb_Arena* root = arena_findroot(a);
+ size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
+ mem_block* block = upb_malloc(root->block_alloc, block_size);
+
+ if (!block) return false;
+ upb_Arena_addblock(a, root, block, block_size);
+ return true;
+}
+
+void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size) {
+ if (!upb_Arena_Allocblock(a, size)) return NULL; /* Out of memory. */
+ UPB_ASSERT(_upb_ArenaHas(a) >= size);
+ return upb_Arena_Malloc(a, size);
+}
+
+static void* upb_Arena_doalloc(upb_alloc* alloc, void* ptr, size_t oldsize,
+ size_t size) {
+ upb_Arena* a = (upb_Arena*)alloc; /* upb_alloc is initial member. */
+ return upb_Arena_Realloc(a, ptr, oldsize, size);
+}
+
+/* Public Arena API ***********************************************************/
+
+upb_Arena* arena_initslow(void* mem, size_t n, upb_alloc* alloc) {
+ const size_t first_block_overhead = sizeof(upb_Arena) + memblock_reserve;
+ upb_Arena* a;
+
+ /* We need to malloc the initial block. */
+ n = first_block_overhead + 256;
+ if (!alloc || !(mem = upb_malloc(alloc, n))) {
+ return NULL;
+ }
+
+ a = UPB_PTR_AT(mem, n - sizeof(*a), upb_Arena);
+ n -= sizeof(*a);
+
+ a->head.alloc.func = &upb_Arena_doalloc;
+ a->block_alloc = alloc;
+ a->parent = a;
+ a->refcount = 1;
+ a->freelist = NULL;
+ a->freelist_tail = NULL;
+ a->cleanup_metadata = upb_cleanup_metadata(NULL, false);
+
+ upb_Arena_addblock(a, a, mem, n);
+
+ return a;
+}
+
+upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
+ upb_Arena* a;
+
+ if (n) {
+ /* Align initial pointer up so that we return properly-aligned pointers. */
+ void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN);
+ size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
+ n = delta <= n ? n - delta : 0;
+ mem = aligned;
+ }
+
+ /* Round block size down to alignof(*a) since we will allocate the arena
+ * itself at the end. */
+ n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_Arena));
+
+ if (UPB_UNLIKELY(n < sizeof(upb_Arena))) {
+ return arena_initslow(mem, n, alloc);
+ }
+
+ a = UPB_PTR_AT(mem, n - sizeof(*a), upb_Arena);
+
+ a->head.alloc.func = &upb_Arena_doalloc;
+ a->block_alloc = alloc;
+ a->parent = a;
+ a->refcount = 1;
+ a->last_size = UPB_MAX(128, n);
+ a->head.ptr = mem;
+ a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
+ a->freelist = NULL;
+ a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
+
+ return a;
+}
+
+static void arena_dofree(upb_Arena* a) {
+ mem_block* block = a->freelist;
+ UPB_ASSERT(a->parent == a);
+ UPB_ASSERT(a->refcount == 0);
+
+ while (block) {
+ /* Load first since we are deleting block. */
+ mem_block* next = block->next;
+
+ if (block->cleanups > 0) {
+ cleanup_ent* end = UPB_PTR_AT(block, block->size, void);
+ cleanup_ent* ptr = end - block->cleanups;
+
+ for (; ptr < end; ptr++) {
+ ptr->cleanup(ptr->ud);
+ }
+ }
+
+ upb_free(a->block_alloc, block);
+ block = next;
+ }
+}
+
+void upb_Arena_Free(upb_Arena* a) {
+ a = arena_findroot(a);
+ if (--a->refcount == 0) arena_dofree(a);
+}
+
+bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func) {
+ cleanup_ent* ent;
+ uint32_t* cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+
+ if (!cleanups || _upb_ArenaHas(a) < sizeof(cleanup_ent)) {
+ if (!upb_Arena_Allocblock(a, 128)) return false; /* Out of memory. */
+ UPB_ASSERT(_upb_ArenaHas(a) >= sizeof(cleanup_ent));
+ cleanups = upb_cleanup_pointer(a->cleanup_metadata);
+ }
+
+ a->head.end -= sizeof(cleanup_ent);
+ ent = (cleanup_ent*)a->head.end;
+ (*cleanups)++;
+ UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
+
+ ent->cleanup = func;
+ ent->ud = ud;
+
+ return true;
+}
+
+bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) {
+ upb_Arena* r1 = arena_findroot(a1);
+ upb_Arena* r2 = arena_findroot(a2);
+
+ if (r1 == r2) return true; /* Already fused. */
+
+ /* Do not fuse initial blocks since we cannot lifetime extend them. */
+ if (upb_cleanup_has_initial_block(r1->cleanup_metadata)) return false;
+ if (upb_cleanup_has_initial_block(r2->cleanup_metadata)) return false;
+
+ /* Only allow fuse with a common allocator */
+ if (r1->block_alloc != r2->block_alloc) return false;
+
+ /* We want to join the smaller tree to the larger tree.
+ * So swap first if they are backwards. */
+ if (r1->refcount < r2->refcount) {
+ upb_Arena* tmp = r1;
+ r1 = r2;
+ r2 = tmp;
+ }
+
+ /* r1 takes over r2's freelist and refcount. */
+ r1->refcount += r2->refcount;
+ if (r2->freelist_tail) {
+ UPB_ASSERT(r2->freelist_tail->next == NULL);
+ r2->freelist_tail->next = r1->freelist;
+ r1->freelist = r2->freelist;
+ }
+ r2->parent = r1;
+ return true;
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/arena.h b/contrib/libs/grpc/third_party/upb/upb/arena.h
new file mode 100644
index 0000000000..0c4fd1b83c
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/arena.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_ARENA_H_
+#define UPB_ARENA_H_
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** upb_alloc *****************************************************************/
+
+/* A upb_alloc is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does). The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+
+struct upb_alloc;
+typedef struct upb_alloc upb_alloc;
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize,
+ size_t size);
+
+struct upb_alloc {
+ upb_alloc_func* func;
+};
+
+UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) {
+ UPB_ASSERT(alloc);
+ return alloc->func(alloc, NULL, 0, size);
+}
+
+UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize,
+ size_t size) {
+ UPB_ASSERT(alloc);
+ return alloc->func(alloc, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) {
+ assert(alloc);
+ alloc->func(alloc, ptr, 0, 0);
+}
+
+/* The global allocator used by upb. Uses the standard malloc()/free(). */
+
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void* upb_gmalloc(size_t size) {
+ return upb_malloc(&upb_alloc_global, size);
+}
+
+UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) {
+ return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); }
+
+/* upb_Arena ******************************************************************/
+
+/* upb_Arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks. Arenas by nature do not require the individual allocations
+ * to be freed. However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb_Arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb_alloc interface, but it would not be as efficient for the
+ * single-threaded case. */
+
+typedef void upb_CleanupFunc(void* ud);
+
+struct upb_Arena;
+typedef struct upb_Arena upb_Arena;
+
+typedef struct {
+ /* We implement the allocator interface.
+ * This must be the first member of upb_Arena!
+ * TODO(haberman): remove once handlers are gone. */
+ upb_alloc alloc;
+
+ char *ptr, *end;
+} _upb_ArenaHead;
+
+/* Creates an arena from the given initial block (if any -- n may be 0).
+ * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
+ * is a fixed-size arena and cannot grow. */
+upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc);
+void upb_Arena_Free(upb_Arena* a);
+bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func);
+bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b);
+void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size);
+
+UPB_INLINE upb_alloc* upb_Arena_Alloc(upb_Arena* a) { return (upb_alloc*)a; }
+
+UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
+ _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+ return (size_t)(h->end - h->ptr);
+}
+
+UPB_INLINE void* _upb_Arena_FastMalloc(upb_Arena* a, size_t size) {
+ _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+ void* ret = h->ptr;
+ UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret);
+ UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size);
+ UPB_UNPOISON_MEMORY_REGION(ret, size);
+
+ h->ptr += size;
+
+#if UPB_ASAN
+ {
+ size_t guard_size = 32;
+ if (_upb_ArenaHas(a) >= guard_size) {
+ h->ptr += guard_size;
+ } else {
+ h->ptr = h->end;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
+ size = UPB_ALIGN_MALLOC(size);
+
+ if (UPB_UNLIKELY(_upb_ArenaHas(a) < size)) {
+ return _upb_Arena_SlowMalloc(a, size);
+ }
+
+ return _upb_Arena_FastMalloc(a, size);
+}
+
+// Shrinks the last alloc from arena.
+// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena.
+// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if
+// this was not the last alloc.
+UPB_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize,
+ size_t size) {
+ _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+ oldsize = UPB_ALIGN_MALLOC(oldsize);
+ size = UPB_ALIGN_MALLOC(size);
+ UPB_ASSERT((char*)ptr + oldsize == h->ptr); // Must be the last alloc.
+ UPB_ASSERT(size <= oldsize);
+ h->ptr = (char*)ptr + size;
+}
+
+UPB_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize,
+ size_t size) {
+ _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+ oldsize = UPB_ALIGN_MALLOC(oldsize);
+ size = UPB_ALIGN_MALLOC(size);
+ bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr;
+
+ if (is_most_recent_alloc) {
+ ptrdiff_t diff = size - oldsize;
+ if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) {
+ h->ptr += diff;
+ return ptr;
+ }
+ } else if (size <= oldsize) {
+ return ptr;
+ }
+
+ void* ret = upb_Arena_Malloc(a, size);
+
+ if (ret && oldsize > 0) {
+ memcpy(ret, ptr, UPB_MIN(oldsize, size));
+ }
+
+ return ret;
+}
+
+UPB_INLINE upb_Arena* upb_Arena_New(void) {
+ return upb_Arena_Init(NULL, 0, &upb_alloc_global);
+}
+
+#include "upb/port_undef.inc"
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_ARENA_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/array.c b/contrib/libs/grpc/third_party/upb/upb/array.c
new file mode 100644
index 0000000000..b4cdc49924
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/array.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/array.h"
+
+#include <string.h>
+
+#include "upb/internal/table.h"
+#include "upb/msg.h"
+#include "upb/port_def.inc"
+
+static const char _upb_CTypeo_sizelg2[12] = {
+ 0,
+ 0, /* kUpb_CType_Bool */
+ 2, /* kUpb_CType_Float */
+ 2, /* kUpb_CType_Int32 */
+ 2, /* kUpb_CType_UInt32 */
+ 2, /* kUpb_CType_Enum */
+ UPB_SIZE(2, 3), /* kUpb_CType_Message */
+ 3, /* kUpb_CType_Double */
+ 3, /* kUpb_CType_Int64 */
+ 3, /* kUpb_CType_UInt64 */
+ UPB_SIZE(3, 4), /* kUpb_CType_String */
+ UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
+};
+
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
+ return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
+}
+
+size_t upb_Array_Size(const upb_Array* arr) { return arr->len; }
+
+upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
+ upb_MessageValue ret;
+ const char* data = _upb_array_constptr(arr);
+ int lg2 = arr->data & 7;
+ UPB_ASSERT(i < arr->len);
+ memcpy(&ret, data + (i << lg2), 1 << lg2);
+ return ret;
+}
+
+void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
+ char* data = _upb_array_ptr(arr);
+ int lg2 = arr->data & 7;
+ UPB_ASSERT(i < arr->len);
+ memcpy(data + (i << lg2), &val, 1 << lg2);
+}
+
+bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
+ if (!upb_Array_Resize(arr, arr->len + 1, arena)) {
+ return false;
+ }
+ upb_Array_Set(arr, arr->len - 1, val);
+ return true;
+}
+
+void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
+ size_t count) {
+ char* data = _upb_array_ptr(arr);
+ int lg2 = arr->data & 7;
+ memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
+}
+
+bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
+ upb_Arena* arena) {
+ UPB_ASSERT(i <= arr->len);
+ UPB_ASSERT(count + arr->len >= count);
+ size_t oldsize = arr->len;
+ if (!upb_Array_Resize(arr, arr->len + count, arena)) {
+ return false;
+ }
+ upb_Array_Move(arr, i + count, i, oldsize - i);
+ return true;
+}
+
+/*
+ * i end arr->len
+ * |------------|XXXXXXXX|--------|
+ */
+void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
+ size_t end = i + count;
+ UPB_ASSERT(i <= end);
+ UPB_ASSERT(end <= arr->len);
+ upb_Array_Move(arr, i, end, arr->len - end);
+ arr->len -= count;
+}
+
+bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
+ return _upb_Array_Resize(arr, size, arena);
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/array.h b/contrib/libs/grpc/third_party/upb/upb/array.h
new file mode 100644
index 0000000000..0715d58430
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/array.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_ARRAY_H_
+#define UPB_ARRAY_H_
+
+#include "google/protobuf/descriptor.upb.h"
+#include "upb/message_value.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
+
+/* Returns the size of the array. */
+size_t upb_Array_Size(const upb_Array* arr);
+
+/* Returns the given element, which must be within the array's current size. */
+upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i);
+
+/* Sets the given element, which must be within the array's current size. */
+void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val);
+
+/* Appends an element to the array. Returns false on allocation failure. */
+bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
+
+/* Moves elements within the array using memmove(). Like memmove(), the source
+ * and destination elements may be overlapping. */
+void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
+ size_t count);
+
+/* Inserts one or more empty elements into the array. Existing elements are
+ * shifted right. The new elements have undefined state and must be set with
+ * `upb_Array_Set()`.
+ * REQUIRES: `i <= upb_Array_Size(arr)` */
+bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
+ upb_Arena* arena);
+
+/* Deletes one or more elements from the array. Existing elements are shifted
+ * left.
+ * REQUIRES: `i + count <= upb_Array_Size(arr)` */
+void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
+
+/* Changes the size of a vector. New elements are initialized to empty/0.
+ * Returns false on allocation failure. */
+bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_ARRAY_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode.c b/contrib/libs/grpc/third_party/upb/upb/decode.c
index 1e07d42c32..d314875313 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode.c
+++ b/contrib/libs/grpc/third_party/upb/upb/decode.c
@@ -30,9 +30,9 @@
#include <setjmp.h>
#include <string.h>
-#include "upb/decode_internal.h"
+#include "upb/internal/decode.h"
+#include "upb/internal/upb.h"
#include "upb/upb.h"
-#include "upb/upb_internal.h"
/* Must be last. */
#include "upb/port_def.inc"
@@ -93,13 +93,11 @@ static const unsigned FIXED64_OK_MASK = (1 << kUpb_FieldType_Double) |
/* Three fake field types for MessageSet. */
#define TYPE_MSGSET_ITEM 19
-#define TYPE_MSGSET_TYPE_ID 20
-#define TYPE_COUNT 20
+#define TYPE_COUNT 19
/* Op: an action to be performed for a wire-type/field-type combination. */
#define OP_UNKNOWN -1 /* Unknown field. */
#define OP_MSGSET_ITEM -2
-#define OP_MSGSET_TYPEID -3
#define OP_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */
#define OP_ENUM 1
#define OP_STRING 4
@@ -131,7 +129,6 @@ static const int8_t varint_ops[] = {
OP_SCALAR_LG2(2), /* SINT32 */
OP_SCALAR_LG2(3), /* SINT64 */
OP_UNKNOWN, /* MSGSET_ITEM */
- OP_MSGSET_TYPEID, /* MSGSET TYPEID */
};
static const int8_t delim_ops[] = {
@@ -156,7 +153,6 @@ static const int8_t delim_ops[] = {
OP_UNKNOWN, /* SINT32 */
OP_UNKNOWN, /* SINT64 */
OP_UNKNOWN, /* MSGSET_ITEM */
- OP_UNKNOWN, /* MSGSET TYPEID */
/* For repeated field type. */
OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
@@ -266,6 +262,18 @@ static const char* decode_tag(upb_Decoder* d, const char* ptr, uint32_t* val) {
}
}
+UPB_FORCEINLINE
+static const char* upb_Decoder_DecodeSize(upb_Decoder* d, const char* ptr,
+ uint32_t* size) {
+ uint64_t size64;
+ ptr = decode_varint64(d, ptr, &size64);
+ if (size64 >= INT32_MAX || ptr - d->end + (int)size64 > d->limit) {
+ decode_err(d, kUpb_DecodeStatus_Malformed);
+ }
+ *size = size64;
+ return ptr;
+}
+
static void decode_munge_int32(wireval* val) {
if (!_upb_IsLittleEndian()) {
/* The next stage will memcpy(dst, &val, 4) */
@@ -300,7 +308,9 @@ static upb_Message* decode_newsubmsg(upb_Decoder* d,
const upb_MiniTable_Sub* subs,
const upb_MiniTable_Field* field) {
const upb_MiniTable* subl = subs[field->submsg_index].submsg;
- return _upb_Message_New_inl(subl, &d->arena);
+ upb_Message* msg = _upb_Message_New_inl(subl, &d->arena);
+ if (!msg) decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ return msg;
}
UPB_NOINLINE
@@ -375,7 +385,7 @@ static const char* decode_togroup(upb_Decoder* d, const char* ptr,
return decode_group(d, ptr, submsg, subl, field->number);
}
-static char* encode_varint32(uint32_t val, char* ptr) {
+static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) {
do {
uint8_t byte = val & 0x7fU;
val >>= 7;
@@ -385,6 +395,18 @@ static char* encode_varint32(uint32_t val, char* ptr) {
return ptr;
}
+static void upb_Decode_AddUnknownVarints(upb_Decoder* d, upb_Message* msg,
+ uint32_t val1, uint32_t val2) {
+ char buf[20];
+ char* end = buf;
+ end = upb_Decoder_EncodeVarint32(val1, end);
+ end = upb_Decoder_EncodeVarint32(val2, end);
+
+ if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
+ decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ }
+}
+
UPB_NOINLINE
static bool decode_checkenum_slow(upb_Decoder* d, const char* ptr,
upb_Message* msg, const upb_MiniTable_Enum* e,
@@ -398,17 +420,9 @@ static bool decode_checkenum_slow(upb_Decoder* d, const char* ptr,
// Unrecognized enum goes into unknown fields.
// For packed fields the tag could be arbitrarily far in the past, so we
- // just re-encode the tag here.
- char buf[20];
- char* end = buf;
+ // just re-encode the tag and value here.
uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
- end = encode_varint32(tag, end);
- end = encode_varint32(v, end);
-
- if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
- decode_err(d, kUpb_DecodeStatus_OutOfMemory);
- }
-
+ upb_Decode_AddUnknownVarints(d, msg, tag, v);
return false;
}
@@ -627,8 +641,23 @@ static const char* decode_tomap(upb_Decoder* d, const char* ptr,
upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
}
+ const char* start = ptr;
ptr = decode_tosubmsg(d, ptr, &ent.k, subs, field, val->size);
- _upb_Map_Set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
+ // check if ent had any unknown fields
+ size_t size;
+ upb_Message_GetUnknown(&ent.k, &size);
+ if (size != 0) {
+ uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited;
+ upb_Decode_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start));
+ if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
+ decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ }
+ } else {
+ if (_upb_Map_Insert(map, &ent.k, map->key_size, &ent.v, map->val_size,
+ &d->arena) == _kUpb_MapInsertStatus_OutOfMemory) {
+ decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ }
+ }
return ptr;
}
@@ -727,25 +756,139 @@ static bool decode_tryfastdispatch(upb_Decoder* d, const char** ptr,
return false;
}
-static const char* decode_msgset(upb_Decoder* d, const char* ptr,
- upb_Message* msg,
- const upb_MiniTable* layout) {
- // We create a temporary upb_MiniTable here and abuse its fields as temporary
- // storage, to avoid creating lots of MessageSet-specific parsing code-paths:
- // 1. We store 'layout' in item_layout.subs. We will need this later as
- // a key to look up extensions for this MessageSet.
- // 2. We use item_layout.fields as temporary storage to store the extension
- // we
- // found when parsing the type id.
- upb_MiniTable item_layout = {
- .subs = (const upb_MiniTable_Sub[]){{.submsg = layout}},
- .fields = NULL,
- .size = 0,
- .field_count = 0,
- .ext = upb_ExtMode_IsMessageSet_ITEM,
- .dense_below = 0,
- .table_mask = -1};
- return decode_group(d, ptr, msg, &item_layout, 1);
+static const char* upb_Decoder_SkipField(upb_Decoder* d, const char* ptr,
+ uint32_t tag) {
+ int field_number = tag >> 3;
+ int wire_type = tag & 7;
+ switch (wire_type) {
+ case kUpb_WireType_Varint: {
+ uint64_t val;
+ return decode_varint64(d, ptr, &val);
+ }
+ case kUpb_WireType_64Bit:
+ return ptr + 8;
+ case kUpb_WireType_32Bit:
+ return ptr + 4;
+ case kUpb_WireType_Delimited: {
+ uint32_t size;
+ ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+ return ptr + size;
+ }
+ case kUpb_WireType_StartGroup:
+ return decode_group(d, ptr, NULL, NULL, field_number);
+ default:
+ decode_err(d, kUpb_DecodeStatus_Malformed);
+ }
+}
+
+enum {
+ kStartItemTag = ((1 << 3) | kUpb_WireType_StartGroup),
+ kEndItemTag = ((1 << 3) | kUpb_WireType_EndGroup),
+ kTypeIdTag = ((2 << 3) | kUpb_WireType_Varint),
+ kMessageTag = ((3 << 3) | kUpb_WireType_Delimited),
+};
+
+static void upb_Decoder_AddKnownMessageSetItem(
+ upb_Decoder* d, upb_Message* msg, const upb_MiniTable_Extension* item_mt,
+ const char* data, uint32_t size) {
+ upb_Message_Extension* ext =
+ _upb_Message_GetOrCreateExtension(msg, item_mt, &d->arena);
+ if (UPB_UNLIKELY(!ext)) decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ upb_Message* submsg = decode_newsubmsg(d, &ext->ext->sub, &ext->ext->field);
+ upb_DecodeStatus status = upb_Decode(data, size, submsg, item_mt->sub.submsg,
+ d->extreg, d->options, &d->arena);
+ memcpy(&ext->data, &submsg, sizeof(submsg));
+ if (status != kUpb_DecodeStatus_Ok) decode_err(d, status);
+}
+
+static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d,
+ upb_Message* msg,
+ uint32_t type_id,
+ const char* message_data,
+ uint32_t message_size) {
+ char buf[60];
+ char* ptr = buf;
+ ptr = upb_Decoder_EncodeVarint32(kStartItemTag, ptr);
+ ptr = upb_Decoder_EncodeVarint32(kTypeIdTag, ptr);
+ ptr = upb_Decoder_EncodeVarint32(type_id, ptr);
+ ptr = upb_Decoder_EncodeVarint32(kMessageTag, ptr);
+ ptr = upb_Decoder_EncodeVarint32(message_size, ptr);
+ char* split = ptr;
+
+ ptr = upb_Decoder_EncodeVarint32(kEndItemTag, ptr);
+ char* end = ptr;
+
+ if (!_upb_Message_AddUnknown(msg, buf, split - buf, &d->arena) ||
+ !_upb_Message_AddUnknown(msg, message_data, message_size, &d->arena) ||
+ !_upb_Message_AddUnknown(msg, split, end - split, &d->arena)) {
+ decode_err(d, kUpb_DecodeStatus_OutOfMemory);
+ }
+}
+
+static void upb_Decoder_AddMessageSetItem(upb_Decoder* d, upb_Message* msg,
+ const upb_MiniTable* layout,
+ uint32_t type_id, const char* data,
+ uint32_t size) {
+ const upb_MiniTable_Extension* item_mt =
+ _upb_extreg_get(d->extreg, layout, type_id);
+ if (item_mt) {
+ upb_Decoder_AddKnownMessageSetItem(d, msg, item_mt, data, size);
+ } else {
+ upb_Decoder_AddUnknownMessageSetItem(d, msg, type_id, data, size);
+ }
+}
+
+static const char* upb_Decoder_DecodeMessageSetItem(
+ upb_Decoder* d, const char* ptr, upb_Message* msg,
+ const upb_MiniTable* layout) {
+ uint32_t type_id = 0;
+ upb_StringView preserved = {NULL, 0};
+ typedef enum {
+ kUpb_HaveId = 1 << 0,
+ kUpb_HavePayload = 1 << 1,
+ } StateMask;
+ StateMask state_mask = 0;
+ while (!decode_isdone(d, &ptr)) {
+ uint32_t tag;
+ ptr = decode_tag(d, ptr, &tag);
+ switch (tag) {
+ case kEndItemTag:
+ return ptr;
+ case kTypeIdTag: {
+ uint64_t tmp;
+ ptr = decode_varint64(d, ptr, &tmp);
+ if (state_mask & kUpb_HaveId) break; // Ignore dup.
+ state_mask |= kUpb_HaveId;
+ type_id = tmp;
+ if (state_mask & kUpb_HavePayload) {
+ upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, preserved.data,
+ preserved.size);
+ }
+ break;
+ }
+ case kMessageTag: {
+ uint32_t size;
+ ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+ const char* data = ptr;
+ ptr += size;
+ if (state_mask & kUpb_HavePayload) break; // Ignore dup.
+ state_mask |= kUpb_HavePayload;
+ if (state_mask & kUpb_HaveId) {
+ upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, data, size);
+ } else {
+ // Out of order, we must preserve the payload.
+ preserved.data = data;
+ preserved.size = size;
+ }
+ break;
+ }
+ default:
+ // We do not preserve unexpected fields inside a message set item.
+ ptr = upb_Decoder_SkipField(d, ptr, tag);
+ break;
+ }
+ }
+ decode_err(d, kUpb_DecodeStatus_Malformed);
}
static const upb_MiniTable_Field* decode_findfield(upb_Decoder* d,
@@ -780,38 +923,18 @@ static const upb_MiniTable_Field* decode_findfield(upb_Decoder* d,
if (d->extreg) {
switch (l->ext) {
- case upb_ExtMode_Extendable: {
+ case kUpb_ExtMode_Extendable: {
const upb_MiniTable_Extension* ext =
_upb_extreg_get(d->extreg, l, field_number);
if (ext) return &ext->field;
break;
}
- case upb_ExtMode_IsMessageSet:
+ case kUpb_ExtMode_IsMessageSet:
if (field_number == _UPB_MSGSET_ITEM) {
static upb_MiniTable_Field item = {0, 0, 0, 0, TYPE_MSGSET_ITEM, 0};
return &item;
}
break;
- case upb_ExtMode_IsMessageSet_ITEM:
- switch (field_number) {
- case _UPB_MSGSET_TYPEID: {
- static upb_MiniTable_Field type_id = {
- 0, 0, 0, 0, TYPE_MSGSET_TYPE_ID, 0};
- return &type_id;
- }
- case _UPB_MSGSET_MESSAGE:
- if (l->fields) {
- // We saw type_id previously and succeeded in looking up msg.
- return l->fields;
- } else {
- // TODO: out of order MessageSet.
- // This is a very rare case: all serializers will emit in-order
- // MessageSets. To hit this case there has to be some kind of
- // re-ordering proxy. We should eventually handle this case, but
- // not today.
- }
- break;
- }
}
}
@@ -851,14 +974,9 @@ static const char* decode_wireval(upb_Decoder* d, const char* ptr,
return ptr + 8;
case kUpb_WireType_Delimited: {
int ndx = field->descriptortype;
- uint64_t size;
if (upb_FieldMode_Get(field) == kUpb_FieldMode_Array) ndx += TYPE_COUNT;
- ptr = decode_varint64(d, ptr, &size);
- if (size >= INT32_MAX || ptr - d->end + (int32_t)size > d->limit) {
- break; /* Length overflow. */
- }
+ ptr = upb_Decoder_DecodeSize(d, ptr, &val->size);
*op = delim_ops[ndx];
- val->size = size;
return ptr;
}
case kUpb_WireType_StartGroup:
@@ -885,11 +1003,11 @@ static const char* decode_known(upb_Decoder* d, const char* ptr,
const upb_MiniTable_Sub* subs = layout->subs;
uint8_t mode = field->mode;
- if (UPB_UNLIKELY(mode & upb_LabelFlags_IsExtension)) {
+ if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) {
const upb_MiniTable_Extension* ext_layout =
(const upb_MiniTable_Extension*)field;
upb_Message_Extension* ext =
- _upb_Message_Getorcreateext(msg, ext_layout, &d->arena);
+ _upb_Message_GetOrCreateExtension(msg, ext_layout, &d->arena);
if (UPB_UNLIKELY(!ext)) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
msg = &ext->data;
subs = &ext->ext->sub;
@@ -1022,14 +1140,8 @@ static const char* decode_msg(upb_Decoder* d, const char* ptr, upb_Message* msg,
ptr = decode_unknown(d, ptr, msg, field_number, wire_type, val);
break;
case OP_MSGSET_ITEM:
- ptr = decode_msgset(d, ptr, msg, layout);
+ ptr = upb_Decoder_DecodeMessageSetItem(d, ptr, msg, layout);
break;
- case OP_MSGSET_TYPEID: {
- const upb_MiniTable_Extension* ext = _upb_extreg_get(
- d->extreg, layout->subs[0].submsg, val.uint64_val);
- if (ext) ((upb_MiniTable*)layout)->fields = &ext->field;
- break;
- }
}
}
}
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode.h b/contrib/libs/grpc/third_party/upb/upb/decode.h
index 1fa8131b7d..0c09497feb 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode.h
+++ b/contrib/libs/grpc/third_party/upb/upb/decode.h
@@ -32,6 +32,7 @@
#ifndef UPB_DECODE_H_
#define UPB_DECODE_H_
+#include "upb/extension_registry.h"
#include "upb/msg.h"
/* Must be last. */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode_fast.c b/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
index e05bf8e0db..a02ad0948f 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
+++ b/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
@@ -37,7 +37,7 @@
#include "upb/decode_fast.h"
-#include "upb/decode_internal.h"
+#include "upb/internal/decode.h"
/* Must be last. */
#include "upb/port_def.inc"
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.c b/contrib/libs/grpc/third_party/upb/upb/def.c
index 363d8bb960..6ddc45bbbb 100644
--- a/contrib/libs/grpc/third_party/upb/upb/def.c
+++ b/contrib/libs/grpc/third_party/upb/upb/def.c
@@ -34,6 +34,7 @@
#include <string.h>
#include "google/protobuf/descriptor.upb.h"
+#include "upb/mini_table.h"
#include "upb/reflection.h"
/* Must be last. */
@@ -86,6 +87,9 @@ struct upb_FieldDef {
bool has_json_name_;
upb_FieldType type_;
upb_Label label_;
+#if UINTPTR_MAX == 0xffffffff
+ uint32_t padding; // Increase size to a multiple of 8.
+#endif
};
struct upb_ExtensionRange {
@@ -106,8 +110,8 @@ struct upb_MessageDef {
upb_strtable ntof;
/* All nested defs.
- * MEM: We could save some space here by putting nested defs in a contigous
- * region and calculating counts from offets or vice-versa. */
+ * MEM: We could save some space here by putting nested defs in a contiguous
+ * region and calculating counts from offsets or vice-versa. */
const upb_FieldDef* fields;
const upb_OneofDef* oneofs;
const upb_ExtensionRange* ext_ranges;
@@ -123,6 +127,9 @@ struct upb_MessageDef {
int nested_ext_count;
bool in_message_set;
upb_WellKnown well_known_type;
+#if UINTPTR_MAX == 0xffffffff
+ uint32_t padding; // Increase size to a multiple of 8.
+#endif
};
struct upb_EnumDef {
@@ -136,6 +143,9 @@ struct upb_EnumDef {
const upb_EnumValueDef* values;
int value_count;
int32_t defaultval;
+#if UINTPTR_MAX == 0xffffffff
+ uint32_t padding; // Increase size to a multiple of 8.
+#endif
};
struct upb_EnumValueDef {
@@ -154,6 +164,9 @@ struct upb_OneofDef {
const upb_FieldDef** fields;
upb_strtable ntof;
upb_inttable itof;
+#if UINTPTR_MAX == 0xffffffff
+ uint32_t padding; // Increase size to a multiple of 8.
+#endif
};
struct upb_FileDef {
@@ -188,6 +201,7 @@ struct upb_MethodDef {
const char* full_name;
const upb_MessageDef* input_type;
const upb_MessageDef* output_type;
+ int index;
bool client_streaming;
bool server_streaming;
};
@@ -246,6 +260,20 @@ static const void* unpack_def(upb_value v, upb_deftype_t type) {
}
static upb_value pack_def(const void* ptr, upb_deftype_t type) {
+ // Our 3-bit pointer tagging requires all pointers to be multiples of 8.
+ // The arena will always yield 8-byte-aligned addresses, however we put
+ // the defs into arrays. For each element in the array to be 8-byte-aligned,
+ // the sizes of each def type must also be a multiple of 8.
+ //
+ // If any of these asserts fail, we need to add or remove padding on 32-bit
+ // machines (64-bit machines will have 8-byte alignment already due to
+ // pointers, which all of these structs have).
+ UPB_ASSERT((sizeof(upb_FieldDef) & UPB_DEFTYPE_MASK) == 0);
+ UPB_ASSERT((sizeof(upb_MessageDef) & UPB_DEFTYPE_MASK) == 0);
+ UPB_ASSERT((sizeof(upb_EnumDef) & UPB_DEFTYPE_MASK) == 0);
+ UPB_ASSERT((sizeof(upb_EnumValueDef) & UPB_DEFTYPE_MASK) == 0);
+ UPB_ASSERT((sizeof(upb_ServiceDef) & UPB_DEFTYPE_MASK) == 0);
+ UPB_ASSERT((sizeof(upb_OneofDef) & UPB_DEFTYPE_MASK) == 0);
uintptr_t num = (uintptr_t)ptr;
UPB_ASSERT((num & UPB_DEFTYPE_MASK) == 0);
num |= type;
@@ -621,6 +649,14 @@ bool upb_FieldDef_IsString(const upb_FieldDef* f) {
upb_FieldDef_CType(f) == kUpb_CType_Bytes;
}
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f) {
+ return upb_FieldDef_Label(f) == kUpb_Label_Optional;
+}
+
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f) {
+ return upb_FieldDef_Label(f) == kUpb_Label_Required;
+}
+
bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) {
return upb_FieldDef_Label(f) == kUpb_Label_Repeated;
}
@@ -980,6 +1016,8 @@ const char* upb_MethodDef_FullName(const upb_MethodDef* m) {
return m->full_name;
}
+int upb_MethodDef_Index(const upb_MethodDef* m) { return m->index; }
+
const char* upb_MethodDef_Name(const upb_MethodDef* m) {
return shortdefname(m->full_name);
}
@@ -1384,7 +1422,12 @@ static uint8_t map_descriptortype(const upb_FieldDef* f) {
if (type == kUpb_FieldType_String && f->file->syntax == kUpb_Syntax_Proto2) {
return kUpb_FieldType_Bytes;
} else if (type == kUpb_FieldType_Enum &&
- f->sub.enumdef->file->syntax == kUpb_Syntax_Proto3) {
+ (f->sub.enumdef->file->syntax == kUpb_Syntax_Proto3 ||
+ UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 ||
+ // TODO(https://github.com/protocolbuffers/upb/issues/541):
+ // fix map enum values to check for unknown enum values and put
+ // them in the unknown field set.
+ upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)))) {
return kUpb_FieldType_Int32;
}
return type;
@@ -1397,43 +1440,43 @@ static void fill_fieldlayout(upb_MiniTable_Field* field,
if (upb_FieldDef_IsMap(f)) {
field->mode =
- kUpb_FieldMode_Map | (upb_FieldRep_Pointer << upb_FieldRep_Shift);
+ kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift);
} else if (upb_FieldDef_IsRepeated(f)) {
field->mode =
- kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift);
+ kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift);
} else {
/* Maps descriptor type -> elem_size_lg2. */
static const uint8_t sizes[] = {
- -1, /* invalid descriptor type */
- upb_FieldRep_8Byte, /* DOUBLE */
- upb_FieldRep_4Byte, /* FLOAT */
- upb_FieldRep_8Byte, /* INT64 */
- upb_FieldRep_8Byte, /* UINT64 */
- upb_FieldRep_4Byte, /* INT32 */
- upb_FieldRep_8Byte, /* FIXED64 */
- upb_FieldRep_4Byte, /* FIXED32 */
- upb_FieldRep_1Byte, /* BOOL */
- upb_FieldRep_StringView, /* STRING */
- upb_FieldRep_Pointer, /* GROUP */
- upb_FieldRep_Pointer, /* MESSAGE */
- upb_FieldRep_StringView, /* BYTES */
- upb_FieldRep_4Byte, /* UINT32 */
- upb_FieldRep_4Byte, /* ENUM */
- upb_FieldRep_4Byte, /* SFIXED32 */
- upb_FieldRep_8Byte, /* SFIXED64 */
- upb_FieldRep_4Byte, /* SINT32 */
- upb_FieldRep_8Byte, /* SINT64 */
+ -1, /* invalid descriptor type */
+ kUpb_FieldRep_8Byte, /* DOUBLE */
+ kUpb_FieldRep_4Byte, /* FLOAT */
+ kUpb_FieldRep_8Byte, /* INT64 */
+ kUpb_FieldRep_8Byte, /* UINT64 */
+ kUpb_FieldRep_4Byte, /* INT32 */
+ kUpb_FieldRep_8Byte, /* FIXED64 */
+ kUpb_FieldRep_4Byte, /* FIXED32 */
+ kUpb_FieldRep_1Byte, /* BOOL */
+ kUpb_FieldRep_StringView, /* STRING */
+ kUpb_FieldRep_Pointer, /* GROUP */
+ kUpb_FieldRep_Pointer, /* MESSAGE */
+ kUpb_FieldRep_StringView, /* BYTES */
+ kUpb_FieldRep_4Byte, /* UINT32 */
+ kUpb_FieldRep_4Byte, /* ENUM */
+ kUpb_FieldRep_4Byte, /* SFIXED32 */
+ kUpb_FieldRep_8Byte, /* SFIXED64 */
+ kUpb_FieldRep_4Byte, /* SINT32 */
+ kUpb_FieldRep_8Byte, /* SINT64 */
};
field->mode = kUpb_FieldMode_Scalar |
- (sizes[field->descriptortype] << upb_FieldRep_Shift);
+ (sizes[field->descriptortype] << kUpb_FieldRep_Shift);
}
if (upb_FieldDef_IsPacked(f)) {
- field->mode |= upb_LabelFlags_IsPacked;
+ field->mode |= kUpb_LabelFlags_IsPacked;
}
if (upb_FieldDef_IsExtension(f)) {
- field->mode |= upb_LabelFlags_IsExtension;
+ field->mode |= kUpb_LabelFlags_IsExtension;
}
}
@@ -1471,12 +1514,12 @@ static void make_layout(symtab_addctx* ctx, const upb_MessageDef* m) {
if (upb_MessageDef_ExtensionRangeCount(m) > 0) {
if (google_protobuf_MessageOptions_message_set_wire_format(m->opts)) {
- l->ext = upb_ExtMode_IsMessageSet;
+ l->ext = kUpb_ExtMode_IsMessageSet;
} else {
- l->ext = upb_ExtMode_Extendable;
+ l->ext = kUpb_ExtMode_Extendable;
}
} else {
- l->ext = upb_ExtMode_NonExtendable;
+ l->ext = kUpb_ExtMode_NonExtendable;
}
/* TODO(haberman): initialize fast tables so that reflection-based parsing
@@ -1551,11 +1594,11 @@ static void make_layout(symtab_addctx* ctx, const upb_MessageDef* m) {
fill_fieldlayout(field, f);
- if (upb_FieldDef_IsSubMessage(f)) {
+ if (field->descriptortype == kUpb_FieldType_Message ||
+ field->descriptortype == kUpb_FieldType_Group) {
field->submsg_index = sublayout_count++;
subs[field->submsg_index].submsg = upb_FieldDef_MessageSubDef(f)->layout;
- } else if (upb_FieldDef_CType(f) == kUpb_CType_Enum &&
- f->file->syntax == kUpb_Syntax_Proto2) {
+ } else if (field->descriptortype == kUpb_FieldType_Enum) {
field->submsg_index = sublayout_count++;
subs[field->submsg_index].subenum = upb_FieldDef_EnumSubDef(f)->layout;
UPB_ASSERT(subs[field->submsg_index].subenum);
@@ -1601,6 +1644,10 @@ static void make_layout(symtab_addctx* ctx, const upb_MessageDef* m) {
if (upb_OneofDef_IsSynthetic(o)) continue;
+ if (o->field_count == 0) {
+ symtab_errf(ctx, "Oneof must have at least one field (%s)", o->full_name);
+ }
+
/* Calculate field size: the max of all field sizes. */
for (int j = 0; j < o->field_count; j++) {
const upb_FieldDef* f = o->fields[j];
@@ -1623,7 +1670,10 @@ static void make_layout(symtab_addctx* ctx, const upb_MessageDef* m) {
l->size = UPB_ALIGN_UP(l->size, 8);
/* Sort fields by number. */
- qsort(fields, upb_MessageDef_numfields(m), sizeof(*fields), field_number_cmp);
+ if (fields) {
+ qsort(fields, upb_MessageDef_numfields(m), sizeof(*fields),
+ field_number_cmp);
+ }
assign_layout_indices(m, l, fields);
}
@@ -1784,8 +1834,8 @@ static const void* symtab_resolveany(symtab_addctx* ctx,
}
} else {
/* Remove components from base until we find an entry or run out. */
- size_t baselen = strlen(base);
- char* tmp = malloc(sym.size + strlen(base) + 1);
+ size_t baselen = base ? strlen(base) : 0;
+ char* tmp = malloc(sym.size + baselen + 1);
while (1) {
char* p = tmp;
if (baselen) {
@@ -1821,10 +1871,10 @@ static const void* symtab_resolve(symtab_addctx* ctx, const char* from_name_dbg,
const void* ret =
symtab_resolveany(ctx, from_name_dbg, base, sym, &found_type);
if (ret && found_type != type) {
- symtab_errf(
- ctx,
- "type mismatch when resolving %s: couldn't find name %s with type=%d",
- from_name_dbg, sym.data, (int)type);
+ symtab_errf(ctx,
+ "type mismatch when resolving %s: couldn't find "
+ "name " UPB_STRINGVIEW_FORMAT " with type=%d",
+ from_name_dbg, UPB_STRINGVIEW_ARGS(sym), (int)type);
}
return ret;
}
@@ -1844,6 +1894,11 @@ static void create_oneofdef(
SET_OPTIONS(o->opts, OneofDescriptorProto, OneofOptions, oneof_proto);
+ upb_value existing_v;
+ if (upb_strtable_lookup2(&m->ntof, name.data, name.size, &existing_v)) {
+ symtab_errf(ctx, "duplicate oneof name (%s)", o->full_name);
+ }
+
v = pack_def(o, UPB_DEFTYPE_ONEOF);
CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, v, ctx->arena));
@@ -2153,7 +2208,7 @@ static void create_fielddef(
f->file = ctx->file; /* Must happen prior to symtab_add(). */
if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
- symtab_errf(ctx, "field has no name (%s)", upb_MessageDef_FullName(m));
+ symtab_errf(ctx, "field has no name");
}
name = google_protobuf_FieldDescriptorProto_name(field_proto);
@@ -2292,8 +2347,7 @@ static void create_fielddef(
}
if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
- int oneof_index =
- google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+ uint32_t oneof_index = google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
upb_OneofDef* oneof;
upb_value v = upb_value_constptr(f);
@@ -2370,6 +2424,7 @@ static void create_service(
m->service = s;
m->full_name = makefullname(ctx, s->full_name, name);
+ m->index = i;
m->client_streaming =
google_protobuf_MethodDescriptorProto_client_streaming(method_proto);
m->server_streaming =
@@ -2397,6 +2452,12 @@ static int count_bits_debug(uint64_t x) {
return n;
}
+static int compare_int32(const void* a_ptr, const void* b_ptr) {
+ int32_t a = *(int32_t*)a_ptr;
+ int32_t b = *(int32_t*)b_ptr;
+ return a < b ? -1 : (a == b ? 0 : 1);
+}
+
upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
const upb_EnumDef* e) {
int n = 0;
@@ -2405,7 +2466,7 @@ upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
for (int i = 0; i < e->value_count; i++) {
uint32_t val = (uint32_t)e->values[i].number;
if (val < 64) {
- mask |= 1 << val;
+ mask |= 1ULL << val;
} else {
n++;
}
@@ -2427,6 +2488,17 @@ upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
UPB_ASSERT(p == values + n);
}
+ // Enums can have duplicate values; we must sort+uniq them.
+ if (values) qsort(values, n, sizeof(*values), &compare_int32);
+
+ int dst = 0;
+ for (int i = 0; i < n; dst++) {
+ int32_t val = values[i];
+ while (i < n && values[i] == val) i++; // Skip duplicates.
+ values[dst] = val;
+ }
+ n = dst;
+
UPB_ASSERT(upb_inttable_count(&e->iton) == n + count_bits_debug(mask));
upb_MiniTable_Enum* layout = symtab_alloc(ctx, sizeof(*layout));
@@ -2510,7 +2582,7 @@ static void create_enumdef(
if (ctx->layout) {
UPB_ASSERT(ctx->enum_count < ctx->layout->enum_count);
e->layout = ctx->layout->enums[ctx->enum_count++];
- UPB_ASSERT(n ==
+ UPB_ASSERT(upb_inttable_count(&e->iton) ==
e->layout->value_count + count_bits_debug(e->layout->mask));
} else {
e->layout = create_enumlayout(ctx, e);
@@ -2781,15 +2853,10 @@ static void resolve_msgdef(symtab_addctx* ctx, upb_MessageDef* m) {
resolve_fielddef(ctx, m->full_name, (upb_FieldDef*)&m->fields[i]);
}
- for (int i = 0; i < m->nested_ext_count; i++) {
- resolve_fielddef(ctx, m->full_name, (upb_FieldDef*)&m->nested_exts[i]);
- }
-
- if (!ctx->layout) make_layout(ctx, m);
-
m->in_message_set = false;
- if (m->nested_ext_count == 1) {
- const upb_FieldDef* ext = &m->nested_exts[0];
+ for (int i = 0; i < m->nested_ext_count; i++) {
+ upb_FieldDef* ext = (upb_FieldDef*)&m->nested_exts[i];
+ resolve_fielddef(ctx, m->full_name, ext);
if (ext->type_ == kUpb_FieldType_Message &&
ext->label_ == kUpb_Label_Optional && ext->sub.msgdef == m &&
google_protobuf_MessageOptions_message_set_wire_format(
@@ -2798,6 +2865,8 @@ static void resolve_msgdef(symtab_addctx* ctx, upb_MessageDef* m) {
}
}
+ if (!ctx->layout) make_layout(ctx, m);
+
for (int i = 0; i < m->nested_msg_count; i++) {
resolve_msgdef(ctx, (upb_MessageDef*)&m->nested_msgs[i]);
}
@@ -2929,7 +2998,7 @@ static void build_filedef(
int32_t* mutable_weak_deps = (int32_t*)file->weak_deps;
for (i = 0; i < n; i++) {
if (weak_deps[i] >= file->dep_count) {
- symtab_errf(ctx, "public_dep %d is out of range", (int)public_deps[i]);
+ symtab_errf(ctx, "weak_dep %d is out of range", (int)weak_deps[i]);
}
mutable_weak_deps[i] = weak_deps[i];
}
@@ -3085,7 +3154,8 @@ const upb_FileDef* upb_DefPool_AddFile(
/* Include here since we want most of this file to be stdio-free. */
#include <stdio.h>
-bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init) {
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+ bool rebuild_minitable) {
/* Since this function should never fail (it would indicate a bug in upb) we
* print errors to stderr instead of returning error status to the user. */
_upb_DefPool_Init** deps = init->deps;
@@ -3102,7 +3172,7 @@ bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init) {
arena = upb_Arena_New();
for (; *deps; deps++) {
- if (!_upb_DefPool_LoadDefInit(s, *deps)) goto err;
+ if (!_upb_DefPool_LoadDefInitEx(s, *deps, rebuild_minitable)) goto err;
}
file = google_protobuf_FileDescriptorProto_parse_ex(
@@ -3119,7 +3189,8 @@ bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init) {
goto err;
}
- if (!_upb_DefPool_AddFile(s, file, init->layout, &status)) {
+ const upb_MiniTable_File* mt = rebuild_minitable ? NULL : init->layout;
+ if (!_upb_DefPool_AddFile(s, file, mt, &status)) {
goto err;
}
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.h b/contrib/libs/grpc/third_party/upb/upb/def.h
index 8b64a53c1d..2cb312df1a 100644
--- a/contrib/libs/grpc/third_party/upb/upb/def.h
+++ b/contrib/libs/grpc/third_party/upb/upb/def.h
@@ -29,7 +29,7 @@
#define UPB_DEF_H_
#include "google/protobuf/descriptor.upb.h"
-#include "upb/table_internal.h"
+#include "upb/internal/table.h"
#include "upb/upb.h"
/* Must be last. */
@@ -116,6 +116,8 @@ const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f);
uint32_t upb_FieldDef_Index(const upb_FieldDef* f);
bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f);
bool upb_FieldDef_IsString(const upb_FieldDef* f);
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f);
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f);
bool upb_FieldDef_IsRepeated(const upb_FieldDef* f);
bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f);
bool upb_FieldDef_IsMap(const upb_FieldDef* f);
@@ -164,11 +166,11 @@ const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
#define kUpb_Any_TypeFieldNumber 1
#define kUpb_Any_ValueFieldNumber 2
-/* Well-known field tag numbers for timestamp messages. */
+/* Well-known field tag numbers for duration messages. */
#define kUpb_Duration_SecondsFieldNumber 1
#define kUpb_Duration_NanosFieldNumber 2
-/* Well-known field tag numbers for duration messages. */
+/* Well-known field tag numbers for timestamp messages. */
#define kUpb_Timestamp_SecondsFieldNumber 1
#define kUpb_Timestamp_NanosFieldNumber 2
@@ -210,6 +212,11 @@ UPB_INLINE bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m) {
return google_protobuf_MessageOptions_map_entry(upb_MessageDef_Options(m));
}
+UPB_INLINE bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m) {
+ return google_protobuf_MessageOptions_message_set_wire_format(
+ upb_MessageDef_Options(m));
+}
+
/* Nested entities. */
int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m);
int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m);
@@ -317,6 +324,7 @@ const google_protobuf_MethodOptions* upb_MethodDef_Options(
const upb_MethodDef* m);
bool upb_MethodDef_HasOptions(const upb_MethodDef* m);
const char* upb_MethodDef_FullName(const upb_MethodDef* m);
+int upb_MethodDef_Index(const upb_MethodDef* m);
const char* upb_MethodDef_Name(const upb_MethodDef* m);
const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m);
const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m);
@@ -389,7 +397,15 @@ typedef struct _upb_DefPool_Init {
upb_StringView descriptor; /* Serialized descriptor. */
} _upb_DefPool_Init;
-bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init);
+// Should only be directly called by tests. This variant lets us suppress
+// the use of compiled-in tables, forcing a rebuild of the tables at runtime.
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+ bool rebuild_minitable);
+
+UPB_INLINE bool _upb_DefPool_LoadDefInit(upb_DefPool* s,
+ const _upb_DefPool_Init* init) {
+ return _upb_DefPool_LoadDefInitEx(s, init, false);
+}
#include "upb/port_undef.inc"
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.hpp b/contrib/libs/grpc/third_party/upb/upb/def.hpp
index d179721d1f..4ce4a22250 100644
--- a/contrib/libs/grpc/third_party/upb/upb/def.hpp
+++ b/contrib/libs/grpc/third_party/upb/upb/def.hpp
@@ -374,11 +374,11 @@ class FileDefPtr {
const upb_FileDef* ptr_;
};
-// Non-const methods in upb::SymbolTable are NOT thread-safe.
-class SymbolTable {
+// Non-const methods in upb::DefPool are NOT thread-safe.
+class DefPool {
public:
- SymbolTable() : ptr_(upb_DefPool_New(), upb_DefPool_Free) {}
- explicit SymbolTable(upb_DefPool* s) : ptr_(s, upb_DefPool_Free) {}
+ DefPool() : ptr_(upb_DefPool_New(), upb_DefPool_Free) {}
+ explicit DefPool(upb_DefPool* s) : ptr_(s, upb_DefPool_Free) {}
const upb_DefPool* ptr() const { return ptr_.get(); }
upb_DefPool* ptr() { return ptr_.get(); }
@@ -410,6 +410,9 @@ class SymbolTable {
std::unique_ptr<upb_DefPool, decltype(&upb_DefPool_Free)> ptr_;
};
+// TODO(b/236632406): This typedef is deprecated. Delete it.
+using SymbolTable = DefPool;
+
inline FileDefPtr MessageDefPtr::file() const {
return FileDefPtr(upb_MessageDef_File(ptr_));
}
diff --git a/contrib/libs/grpc/third_party/upb/upb/encode.c b/contrib/libs/grpc/third_party/upb/upb/encode.c
index c339c9d81e..048ecd2396 100644
--- a/contrib/libs/grpc/third_party/upb/upb/encode.c
+++ b/contrib/libs/grpc/third_party/upb/upb/encode.c
@@ -32,6 +32,7 @@
#include <setjmp.h>
#include <string.h>
+#include "upb/extension_registry.h"
#include "upb/msg_internal.h"
#include "upb/upb.h"
@@ -76,7 +77,9 @@ static size_t upb_roundup_pow2(size_t bytes) {
return ret;
}
-UPB_NORETURN static void encode_err(upb_encstate* e) { UPB_LONGJMP(e->err, 1); }
+UPB_NORETURN static void encode_err(upb_encstate* e, upb_EncodeStatus s) {
+ UPB_LONGJMP(e->err, s);
+}
UPB_NOINLINE
static void encode_growbuffer(upb_encstate* e, size_t bytes) {
@@ -84,7 +87,7 @@ static void encode_growbuffer(upb_encstate* e, size_t bytes) {
size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
char* new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
- if (!new_buf) encode_err(e);
+ if (!new_buf) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
/* We want previous data at the end, realloc() put it at the beginning. */
if (old_size > 0) {
@@ -255,7 +258,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem,
if (submsg == NULL) {
return;
}
- if (--e->depth == 0) encode_err(e);
+ if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
encode_tag(e, f->number, kUpb_WireType_EndGroup);
encode_message(e, submsg, subm, &size);
wire_type = kUpb_WireType_StartGroup;
@@ -269,7 +272,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem,
if (submsg == NULL) {
return;
}
- if (--e->depth == 0) encode_err(e);
+ if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
encode_message(e, submsg, subm, &size);
encode_varint(e, size);
wire_type = kUpb_WireType_Delimited;
@@ -288,7 +291,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg,
const upb_MiniTable_Sub* subs,
const upb_MiniTable_Field* f) {
const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
- bool packed = f->mode & upb_LabelFlags_IsPacked;
+ bool packed = f->mode & kUpb_LabelFlags_IsPacked;
size_t pre_len = e->limit - e->ptr;
if (arr == NULL || arr->len == 0) {
@@ -355,7 +358,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg,
const void* const* start = _upb_array_constptr(arr);
const void* const* ptr = start + arr->len;
const upb_MiniTable* subm = subs[f->submsg_index].submsg;
- if (--e->depth == 0) encode_err(e);
+ if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
do {
size_t size;
ptr--;
@@ -370,7 +373,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg,
const void* const* start = _upb_array_constptr(arr);
const void* const* ptr = start + arr->len;
const upb_MiniTable* subm = subs[f->submsg_index].submsg;
- if (--e->depth == 0) encode_err(e);
+ if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
do {
size_t size;
ptr--;
@@ -413,7 +416,7 @@ static void encode_map(upb_encstate* e, const upb_Message* msg,
if (map == NULL) return;
- if (e->options & kUpb_Encode_Deterministic) {
+ if (e->options & kUpb_EncodeOption_Deterministic) {
_upb_sortedmap sorted;
_upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
&sorted);
@@ -442,23 +445,29 @@ static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
if (f->presence == 0) {
/* Proto3 presence or map/array. */
const void* mem = UPB_PTR_AT(msg, f->offset, void);
- switch (f->mode >> upb_FieldRep_Shift) {
- case upb_FieldRep_1Byte: {
+ switch (f->mode >> kUpb_FieldRep_Shift) {
+ case kUpb_FieldRep_1Byte: {
char ch;
memcpy(&ch, mem, 1);
return ch != 0;
}
- case upb_FieldRep_4Byte: {
+#if UINTPTR_MAX == 0xffffffff
+ case kUpb_FieldRep_Pointer:
+#endif
+ case kUpb_FieldRep_4Byte: {
uint32_t u32;
memcpy(&u32, mem, 4);
return u32 != 0;
}
- case upb_FieldRep_8Byte: {
+#if UINTPTR_MAX != 0xffffffff
+ case kUpb_FieldRep_Pointer:
+#endif
+ case kUpb_FieldRep_8Byte: {
uint64_t u64;
memcpy(&u64, mem, 8);
return u64 != 0;
}
- case upb_FieldRep_StringView: {
+ case kUpb_FieldRep_StringView: {
const upb_StringView* str = (const upb_StringView*)mem;
return str->size != 0;
}
@@ -514,16 +523,16 @@ static void encode_message(upb_encstate* e, const upb_Message* msg,
const upb_MiniTable* m, size_t* size) {
size_t pre_len = e->limit - e->ptr;
- if ((e->options & kUpb_Encode_CheckRequired) && m->required_count) {
+ if ((e->options & kUpb_EncodeOption_CheckRequired) && m->required_count) {
uint64_t msg_head;
memcpy(&msg_head, msg, 8);
msg_head = _upb_BigEndian_Swap64(msg_head);
if (upb_MiniTable_requiredmask(m) & ~msg_head) {
- encode_err(e);
+ encode_err(e, kUpb_EncodeStatus_MissingRequired);
}
}
- if ((e->options & kUpb_Encode_SkipUnknown) == 0) {
+ if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) {
size_t unknown_size;
const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
@@ -532,7 +541,7 @@ static void encode_message(upb_encstate* e, const upb_Message* msg,
}
}
- if (m->ext != upb_ExtMode_NonExtendable) {
+ if (m->ext != kUpb_ExtMode_NonExtendable) {
/* Encode all extensions together. Unlike C++, we do not attempt to keep
* these in field number order relative to normal fields or even to each
* other. */
@@ -541,7 +550,7 @@ static void encode_message(upb_encstate* e, const upb_Message* msg,
if (ext_count) {
const upb_Message_Extension* end = ext + ext_count;
for (; ext != end; ext++) {
- if (UPB_UNLIKELY(m->ext == upb_ExtMode_IsMessageSet)) {
+ if (UPB_UNLIKELY(m->ext == kUpb_ExtMode_IsMessageSet)) {
encode_msgset_item(e, ext);
} else {
encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
@@ -564,8 +573,9 @@ static void encode_message(upb_encstate* e, const upb_Message* msg,
*size = (e->limit - e->ptr) - pre_len;
}
-char* upb_Encode(const void* msg, const upb_MiniTable* l, int options,
- upb_Arena* arena, size_t* size) {
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+ int options, upb_Arena* arena, char** buf,
+ size_t* size) {
upb_encstate e;
unsigned depth = (unsigned)options >> 16;
@@ -576,23 +586,28 @@ char* upb_Encode(const void* msg, const upb_MiniTable* l, int options,
e.depth = depth ? depth : 64;
e.options = options;
_upb_mapsorter_init(&e.sorter);
- char* ret = NULL;
- if (UPB_SETJMP(e.err)) {
- *size = 0;
- ret = NULL;
- } else {
+ upb_EncodeStatus status = UPB_SETJMP(e.err);
+
+ // Unfortunately we must continue to perform hackery here because there are
+ // code paths which blindly copy the returned pointer without bothering to
+ // check for errors until much later (b/235839510). So we still set *buf to
+ // NULL on error and we still set it to non-NULL on a successful empty result.
+ if (status == kUpb_EncodeStatus_Ok) {
encode_message(&e, msg, l, size);
*size = e.limit - e.ptr;
if (*size == 0) {
static char ch;
- ret = &ch;
+ *buf = &ch;
} else {
UPB_ASSERT(e.ptr);
- ret = e.ptr;
+ *buf = e.ptr;
}
+ } else {
+ *buf = NULL;
+ *size = 0;
}
_upb_mapsorter_destroy(&e.sorter);
- return ret;
+ return status;
}
diff --git a/contrib/libs/grpc/third_party/upb/upb/encode.h b/contrib/libs/grpc/third_party/upb/upb/encode.h
index 906b6f0c35..791d84a74c 100644
--- a/contrib/libs/grpc/third_party/upb/upb/encode.h
+++ b/contrib/libs/grpc/third_party/upb/upb/encode.h
@@ -26,7 +26,7 @@
*/
/*
- * upb_Encode: parsing into a upb_Message using a upb_MiniTable.
+ * upb_Encode: parsing from a upb_Message using a upb_MiniTable.
*/
#ifndef UPB_ENCODE_H_
@@ -48,19 +48,29 @@ enum {
*
* If your proto contains maps, the encoder will need to malloc()/free()
* memory during encode. */
- kUpb_Encode_Deterministic = 1,
+ kUpb_EncodeOption_Deterministic = 1,
/* When set, unknown fields are not printed. */
- kUpb_Encode_SkipUnknown = 2,
+ kUpb_EncodeOption_SkipUnknown = 2,
/* When set, the encode will fail if any required fields are missing. */
- kUpb_Encode_CheckRequired = 4,
+ kUpb_EncodeOption_CheckRequired = 4,
};
#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
-char* upb_Encode(const void* msg, const upb_MiniTable* l, int options,
- upb_Arena* arena, size_t* size);
+typedef enum {
+ kUpb_EncodeStatus_Ok = 0,
+ kUpb_EncodeStatus_OutOfMemory = 1, // Arena alloc failed
+ kUpb_EncodeStatus_MaxDepthExceeded = 2, // Exceeded UPB_ENCODE_MAXDEPTH
+
+ // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded.
+ kUpb_EncodeStatus_MissingRequired = 3,
+} upb_EncodeStatus;
+
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+ int options, upb_Arena* arena, char** buf,
+ size_t* size);
#include "upb/port_undef.inc"
diff --git a/contrib/libs/grpc/third_party/upb/upb/extension_registry.c b/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
new file mode 100644
index 0000000000..921cf227dd
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/extension_registry.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/extension_registry.h"
+
+#include "upb/internal/table.h"
+#include "upb/msg.h"
+#include "upb/msg_internal.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+struct upb_ExtensionRegistry {
+ upb_Arena* arena;
+ upb_strtable exts; /* Key is upb_MiniTable* concatenated with fieldnum. */
+};
+
+#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
+
+static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
+ memcpy(buf, &l, sizeof(l));
+ memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
+}
+
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
+ upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
+ if (!r) return NULL;
+ r->arena = arena;
+ if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
+ return r;
+}
+
+bool _upb_extreg_add(upb_ExtensionRegistry* r,
+ const upb_MiniTable_Extension** e, size_t count) {
+ char buf[EXTREG_KEY_SIZE];
+ const upb_MiniTable_Extension** start = e;
+ const upb_MiniTable_Extension** end = UPB_PTRADD(e, count);
+ for (; e < end; e++) {
+ const upb_MiniTable_Extension* ext = *e;
+ extreg_key(buf, ext->extendee, ext->field.number);
+ if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
+ upb_value_constptr(ext), r->arena)) {
+ goto failure;
+ }
+ }
+ return true;
+
+failure:
+ /* Back out the entries previously added. */
+ for (end = e, e = start; e < end; e++) {
+ const upb_MiniTable_Extension* ext = *e;
+ extreg_key(buf, ext->extendee, ext->field.number);
+ upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
+ }
+ return false;
+}
+
+const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
+ const upb_MiniTable* l,
+ uint32_t num) {
+ char buf[EXTREG_KEY_SIZE];
+ upb_value v;
+ extreg_key(buf, l, num);
+ if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
+ return upb_value_getconstptr(v);
+ } else {
+ return NULL;
+ }
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/extension_registry.h b/contrib/libs/grpc/third_party/upb/upb/extension_registry.h
new file mode 100644
index 0000000000..0e0a4440ca
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/extension_registry.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_EXTENSION_REGISTRY_H_
+#define UPB_EXTENSION_REGISTRY_H_
+
+#include <stddef.h>
+
+#include "upb/upb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Extension registry: a dynamic data structure that stores a map of:
+ * (upb_MiniTable, number) -> extension info
+ *
+ * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
+ * binary format.
+ *
+ * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
+ * objects. Like all mini-table objects, it is suitable for reflection-less
+ * builds that do not want to expose names into the binary.
+ *
+ * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
+ * allocation and dynamic initialization:
+ * * If reflection is being used, then upb_DefPool will construct an appropriate
+ * upb_ExtensionRegistry automatically.
+ * * For a mini-table only build, the user must manually construct the
+ * upb_ExtensionRegistry and populate it with all of the extensions the user
+ * cares about.
+ * * A third alternative is to manually unpack relevant extensions after the
+ * main parse is complete, similar to how Any works. This is perhaps the
+ * nicest solution from the perspective of reducing dependencies, avoiding
+ * dynamic memory allocation, and avoiding the need to parse uninteresting
+ * extensions. The downsides are:
+ * (1) parse errors are not caught during the main parse
+ * (2) the CPU hit of parsing comes during access, which could cause an
+ * undesirable stutter in application performance.
+ *
+ * Users cannot directly get or put into this map. Users can only add the
+ * extensions from a generated module and pass the extension registry to the
+ * binary decoder.
+ *
+ * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
+ * reflection do not need to populate a upb_ExtensionRegistry directly.
+ */
+
+struct upb_ExtensionRegistry;
+typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
+
+/* Creates a upb_ExtensionRegistry in the given arena. The arena must outlive
+ * any use of the extreg. */
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_EXTENSION_REGISTRY_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode_internal.h b/contrib/libs/grpc/third_party/upb/upb/internal/decode.h
index 11bb9aa095..708874c9c7 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode_internal.h
+++ b/contrib/libs/grpc/third_party/upb/upb/internal/decode.h
@@ -30,15 +30,15 @@
* decode.c and decode_fast.c.
*/
-#ifndef UPB_DECODE_INT_H_
-#define UPB_DECODE_INT_H_
+#ifndef UPB_INTERNAL_DECODE_H_
+#define UPB_INTERNAL_DECODE_H_
#include <setjmp.h>
-#include "third_party/utf8_range/utf8_range.h"
#include "upb/decode.h"
+#include "upb/internal/upb.h"
#include "upb/msg_internal.h"
-#include "upb/upb_internal.h"
+#include "third_party/utf8_range/utf8_range.h"
/* Must be last. */
#include "upb/port_def.inc"
@@ -208,4 +208,4 @@ UPB_INLINE void decode_poplimit(upb_Decoder* d, const char* ptr,
#include "upb/port_undef.inc"
-#endif /* UPB_DECODE_INT_H_ */
+#endif /* UPB_INTERNAL_DECODE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/table_internal.h b/contrib/libs/grpc/third_party/upb/upb/internal/table.h
index 9fb2d238cd..bc647be83f 100644
--- a/contrib/libs/grpc/third_party/upb/upb/table_internal.h
+++ b/contrib/libs/grpc/third_party/upb/upb/internal/table.h
@@ -44,8 +44,8 @@
* mode, we check this on insert and lookup.
*/
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
+#ifndef UPB_INTERNAL_TABLE_H_
+#define UPB_INTERNAL_TABLE_H_
#include <stdint.h>
#include <string.h>
@@ -215,8 +215,8 @@ UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) {
void upb_strtable_clear(upb_strtable* t);
/* Inserts the given key into the hashtable with the given value. The key must
- * not already exist in the hash table. For string tables, the key must be
- * NULL-terminated, and the table will make an internal copy of the key.
+ * not already exist in the hash table. For strtables, the key is not required
+ * to be NULL-terminated, and the table will make an internal copy of the key.
* Inttables must not insert a value of UINTPTR_MAX.
*
* If a table resize was required but memory allocation failed, false is
@@ -374,10 +374,12 @@ void upb_inttable_iter_setdone(upb_inttable_iter* i);
bool upb_inttable_iter_isequal(const upb_inttable_iter* i1,
const upb_inttable_iter* i2);
+uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"
-#endif /* UPB_TABLE_H_ */
+#endif /* UPB_INTERNAL_TABLE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb_internal.h b/contrib/libs/grpc/third_party/upb/upb/internal/upb.h
index 1eb166f7d3..cdc8bfc228 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb_internal.h
+++ b/contrib/libs/grpc/third_party/upb/upb/internal/upb.h
@@ -25,8 +25,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef UPB_INT_H_
-#define UPB_INT_H_
+#ifndef UPB_INTERNAL_UPB_H_
+#define UPB_INTERNAL_UPB_H_
#include "upb/upb.h"
@@ -65,4 +65,4 @@ enum { kUpb_RoundTripBufferSize = 32 };
void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size);
void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size);
-#endif /* UPB_INT_H_ */
+#endif /* UPB_INTERNAL_UPB_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/internal/vsnprintf_compat.h b/contrib/libs/grpc/third_party/upb/upb/internal/vsnprintf_compat.h
new file mode 100644
index 0000000000..a9d84bb6fe
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/internal/vsnprintf_compat.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_INTERNAL_VSNPRINTF_COMPAT_H_
+#define UPB_INTERNAL_VSNPRINTF_COMPAT_H_
+
+#include <stdio.h>
+
+// Must be last.
+#include "upb/port_def.inc"
+
+UPB_INLINE int _upb_vsnprintf(char* buf, size_t size, const char* fmt,
+ va_list ap) {
+#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
+ // The msvc runtime has a non-conforming vsnprintf() that requires the
+ // following compatibility code to become conformant.
+ int n = -1;
+ if (size != 0) n = _vsnprintf_s(buf, size, _TRUNCATE, fmt, ap);
+ if (n == -1) n = _vscprintf(fmt, ap);
+ return n;
+#else
+ return vsnprintf(buf, size, fmt, ap);
+#endif
+}
+
+#include "upb/port_undef.inc"
+
+#endif // UPB_INTERNAL_VSNPRINTF_COMPAT_H_
diff --git a/contrib/libs/grpc/third_party/upb/upb/json_decode.c b/contrib/libs/grpc/third_party/upb/upb/json_decode.c
new file mode 100644
index 0000000000..4f79294ef8
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/json_decode.c
@@ -0,0 +1,1512 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/json_decode.h"
+
+#include <errno.h>
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "upb/encode.h"
+#include "upb/reflection.h"
+
+/* Special header, must be included last. */
+#include "upb/port_def.inc"
+
+typedef struct {
+ const char *ptr, *end;
+ upb_Arena* arena; /* TODO: should we have a tmp arena for tmp data? */
+ const upb_DefPool* symtab;
+ int depth;
+ upb_Status* status;
+ jmp_buf err;
+ int line;
+ const char* line_begin;
+ bool is_first;
+ int options;
+ const upb_FieldDef* debug_field;
+} jsondec;
+
+enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL };
+
+/* Forward declarations of mutually-recursive functions. */
+static void jsondec_wellknown(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m);
+static upb_MessageValue jsondec_value(jsondec* d, const upb_FieldDef* f);
+static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m);
+static void jsondec_object(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m);
+
+static bool jsondec_streql(upb_StringView str, const char* lit) {
+ return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0;
+}
+
+static bool jsondec_isnullvalue(const upb_FieldDef* f) {
+ return upb_FieldDef_CType(f) == kUpb_CType_Enum &&
+ strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)),
+ "google.protobuf.NullValue") == 0;
+}
+
+static bool jsondec_isvalue(const upb_FieldDef* f) {
+ return (upb_FieldDef_CType(f) == kUpb_CType_Message &&
+ upb_MessageDef_WellKnownType(upb_FieldDef_MessageSubDef(f)) ==
+ kUpb_WellKnown_Value) ||
+ jsondec_isnullvalue(f);
+}
+
+UPB_NORETURN static void jsondec_err(jsondec* d, const char* msg) {
+ upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: %s", d->line,
+ (int)(d->ptr - d->line_begin), msg);
+ UPB_LONGJMP(d->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsondec_errf(jsondec* d, const char* fmt, ...) {
+ va_list argp;
+ upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: ", d->line,
+ (int)(d->ptr - d->line_begin));
+ va_start(argp, fmt);
+ upb_Status_VAppendErrorFormat(d->status, fmt, argp);
+ va_end(argp);
+ UPB_LONGJMP(d->err, 1);
+}
+
+static void jsondec_skipws(jsondec* d) {
+ while (d->ptr != d->end) {
+ switch (*d->ptr) {
+ case '\n':
+ d->line++;
+ d->line_begin = d->ptr;
+ /* Fallthrough. */
+ case '\r':
+ case '\t':
+ case ' ':
+ d->ptr++;
+ break;
+ default:
+ return;
+ }
+ }
+ jsondec_err(d, "Unexpected EOF");
+}
+
+static bool jsondec_tryparsech(jsondec* d, char ch) {
+ if (d->ptr == d->end || *d->ptr != ch) return false;
+ d->ptr++;
+ return true;
+}
+
+static void jsondec_parselit(jsondec* d, const char* lit) {
+ size_t avail = d->end - d->ptr;
+ size_t len = strlen(lit);
+ if (avail < len || memcmp(d->ptr, lit, len) != 0) {
+ jsondec_errf(d, "Expected: '%s'", lit);
+ }
+ d->ptr += len;
+}
+
+static void jsondec_wsch(jsondec* d, char ch) {
+ jsondec_skipws(d);
+ if (!jsondec_tryparsech(d, ch)) {
+ jsondec_errf(d, "Expected: '%c'", ch);
+ }
+}
+
+static void jsondec_true(jsondec* d) { jsondec_parselit(d, "true"); }
+static void jsondec_false(jsondec* d) { jsondec_parselit(d, "false"); }
+static void jsondec_null(jsondec* d) { jsondec_parselit(d, "null"); }
+
+static void jsondec_entrysep(jsondec* d) {
+ jsondec_skipws(d);
+ jsondec_parselit(d, ":");
+}
+
+static int jsondec_rawpeek(jsondec* d) {
+ switch (*d->ptr) {
+ case '{':
+ return JD_OBJECT;
+ case '[':
+ return JD_ARRAY;
+ case '"':
+ return JD_STRING;
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return JD_NUMBER;
+ case 't':
+ return JD_TRUE;
+ case 'f':
+ return JD_FALSE;
+ case 'n':
+ return JD_NULL;
+ default:
+ jsondec_errf(d, "Unexpected character: '%c'", *d->ptr);
+ }
+}
+
+/* JSON object/array **********************************************************/
+
+/* These are used like so:
+ *
+ * jsondec_objstart(d);
+ * while (jsondec_objnext(d)) {
+ * ...
+ * }
+ * jsondec_objend(d) */
+
+static int jsondec_peek(jsondec* d) {
+ jsondec_skipws(d);
+ return jsondec_rawpeek(d);
+}
+
+static void jsondec_push(jsondec* d) {
+ if (--d->depth < 0) {
+ jsondec_err(d, "Recursion limit exceeded");
+ }
+ d->is_first = true;
+}
+
+static bool jsondec_seqnext(jsondec* d, char end_ch) {
+ bool is_first = d->is_first;
+ d->is_first = false;
+ jsondec_skipws(d);
+ if (*d->ptr == end_ch) return false;
+ if (!is_first) jsondec_parselit(d, ",");
+ return true;
+}
+
+static void jsondec_arrstart(jsondec* d) {
+ jsondec_push(d);
+ jsondec_wsch(d, '[');
+}
+
+static void jsondec_arrend(jsondec* d) {
+ d->depth++;
+ jsondec_wsch(d, ']');
+}
+
+static bool jsondec_arrnext(jsondec* d) { return jsondec_seqnext(d, ']'); }
+
+static void jsondec_objstart(jsondec* d) {
+ jsondec_push(d);
+ jsondec_wsch(d, '{');
+}
+
+static void jsondec_objend(jsondec* d) {
+ d->depth++;
+ jsondec_wsch(d, '}');
+}
+
+static bool jsondec_objnext(jsondec* d) {
+ if (!jsondec_seqnext(d, '}')) return false;
+ if (jsondec_peek(d) != JD_STRING) {
+ jsondec_err(d, "Object must start with string");
+ }
+ return true;
+}
+
+/* JSON number ****************************************************************/
+
+static bool jsondec_tryskipdigits(jsondec* d) {
+ const char* start = d->ptr;
+
+ while (d->ptr < d->end) {
+ if (*d->ptr < '0' || *d->ptr > '9') {
+ break;
+ }
+ d->ptr++;
+ }
+
+ return d->ptr != start;
+}
+
+static void jsondec_skipdigits(jsondec* d) {
+ if (!jsondec_tryskipdigits(d)) {
+ jsondec_err(d, "Expected one or more digits");
+ }
+}
+
+static double jsondec_number(jsondec* d) {
+ const char* start = d->ptr;
+
+ assert(jsondec_rawpeek(d) == JD_NUMBER);
+
+ /* Skip over the syntax of a number, as specified by JSON. */
+ if (*d->ptr == '-') d->ptr++;
+
+ if (jsondec_tryparsech(d, '0')) {
+ if (jsondec_tryskipdigits(d)) {
+ jsondec_err(d, "number cannot have leading zero");
+ }
+ } else {
+ jsondec_skipdigits(d);
+ }
+
+ if (d->ptr == d->end) goto parse;
+ if (jsondec_tryparsech(d, '.')) {
+ jsondec_skipdigits(d);
+ }
+ if (d->ptr == d->end) goto parse;
+
+ if (*d->ptr == 'e' || *d->ptr == 'E') {
+ d->ptr++;
+ if (d->ptr == d->end) {
+ jsondec_err(d, "Unexpected EOF in number");
+ }
+ if (*d->ptr == '+' || *d->ptr == '-') {
+ d->ptr++;
+ }
+ jsondec_skipdigits(d);
+ }
+
+parse:
+ /* Having verified the syntax of a JSON number, use strtod() to parse
+ * (strtod() accepts a superset of JSON syntax). */
+ errno = 0;
+ {
+ char* end;
+ double val = strtod(start, &end);
+ assert(end == d->ptr);
+
+ /* Currently the min/max-val conformance tests fail if we check this. Does
+ * this mean the conformance tests are wrong or strtod() is wrong, or
+ * something else? Investigate further. */
+ /*
+ if (errno == ERANGE) {
+ jsondec_err(d, "Number out of range");
+ }
+ */
+
+ if (val > DBL_MAX || val < -DBL_MAX) {
+ jsondec_err(d, "Number out of range");
+ }
+
+ return val;
+ }
+}
+
+/* JSON string ****************************************************************/
+
+static char jsondec_escape(jsondec* d) {
+ switch (*d->ptr++) {
+ case '"':
+ return '\"';
+ case '\\':
+ return '\\';
+ case '/':
+ return '/';
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ default:
+ jsondec_err(d, "Invalid escape char");
+ }
+}
+
+static uint32_t jsondec_codepoint(jsondec* d) {
+ uint32_t cp = 0;
+ const char* end;
+
+ if (d->end - d->ptr < 4) {
+ jsondec_err(d, "EOF inside string");
+ }
+
+ end = d->ptr + 4;
+ while (d->ptr < end) {
+ char ch = *d->ptr++;
+ if (ch >= '0' && ch <= '9') {
+ ch -= '0';
+ } else if (ch >= 'a' && ch <= 'f') {
+ ch = ch - 'a' + 10;
+ } else if (ch >= 'A' && ch <= 'F') {
+ ch = ch - 'A' + 10;
+ } else {
+ jsondec_err(d, "Invalid hex digit");
+ }
+ cp = (cp << 4) | ch;
+ }
+
+ return cp;
+}
+
+/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */
+static size_t jsondec_unicode(jsondec* d, char* out) {
+ uint32_t cp = jsondec_codepoint(d);
+ if (cp >= 0xd800 && cp <= 0xdbff) {
+ /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */
+ uint32_t high = cp;
+ uint32_t low;
+ jsondec_parselit(d, "\\u");
+ low = jsondec_codepoint(d);
+ if (low < 0xdc00 || low > 0xdfff) {
+ jsondec_err(d, "Invalid low surrogate");
+ }
+ cp = (high & 0x3ff) << 10;
+ cp |= (low & 0x3ff);
+ cp += 0x10000;
+ } else if (cp >= 0xdc00 && cp <= 0xdfff) {
+ jsondec_err(d, "Unpaired low surrogate");
+ }
+
+ /* Write to UTF-8 */
+ if (cp <= 0x7f) {
+ out[0] = cp;
+ return 1;
+ } else if (cp <= 0x07FF) {
+ out[0] = ((cp >> 6) & 0x1F) | 0xC0;
+ out[1] = ((cp >> 0) & 0x3F) | 0x80;
+ return 2;
+ } else if (cp <= 0xFFFF) {
+ out[0] = ((cp >> 12) & 0x0F) | 0xE0;
+ out[1] = ((cp >> 6) & 0x3F) | 0x80;
+ out[2] = ((cp >> 0) & 0x3F) | 0x80;
+ return 3;
+ } else if (cp < 0x10FFFF) {
+ out[0] = ((cp >> 18) & 0x07) | 0xF0;
+ out[1] = ((cp >> 12) & 0x3f) | 0x80;
+ out[2] = ((cp >> 6) & 0x3f) | 0x80;
+ out[3] = ((cp >> 0) & 0x3f) | 0x80;
+ return 4;
+ } else {
+ jsondec_err(d, "Invalid codepoint");
+ }
+}
+
+static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) {
+ size_t oldsize = *buf_end - *buf;
+ size_t len = *end - *buf;
+ size_t size = UPB_MAX(8, 2 * oldsize);
+
+ *buf = upb_Arena_Realloc(d->arena, *buf, len, size);
+ if (!*buf) jsondec_err(d, "Out of memory");
+
+ *end = *buf + len;
+ *buf_end = *buf + size;
+}
+
+static upb_StringView jsondec_string(jsondec* d) {
+ char* buf = NULL;
+ char* end = NULL;
+ char* buf_end = NULL;
+
+ jsondec_skipws(d);
+
+ if (*d->ptr++ != '"') {
+ jsondec_err(d, "Expected string");
+ }
+
+ while (d->ptr < d->end) {
+ char ch = *d->ptr++;
+
+ if (end == buf_end) {
+ jsondec_resize(d, &buf, &end, &buf_end);
+ }
+
+ switch (ch) {
+ case '"': {
+ upb_StringView ret;
+ ret.data = buf;
+ ret.size = end - buf;
+ *end = '\0'; /* Needed for possible strtod(). */
+ return ret;
+ }
+ case '\\':
+ if (d->ptr == d->end) goto eof;
+ if (*d->ptr == 'u') {
+ d->ptr++;
+ if (buf_end - end < 4) {
+ /* Allow space for maximum-sized code point (4 bytes). */
+ jsondec_resize(d, &buf, &end, &buf_end);
+ }
+ end += jsondec_unicode(d, end);
+ } else {
+ *end++ = jsondec_escape(d);
+ }
+ break;
+ default:
+ if ((unsigned char)*d->ptr < 0x20) {
+ jsondec_err(d, "Invalid char in JSON string");
+ }
+ *end++ = ch;
+ break;
+ }
+ }
+
+eof:
+ jsondec_err(d, "EOF inside string");
+}
+
+static void jsondec_skipval(jsondec* d) {
+ switch (jsondec_peek(d)) {
+ case JD_OBJECT:
+ jsondec_objstart(d);
+ while (jsondec_objnext(d)) {
+ jsondec_string(d);
+ jsondec_entrysep(d);
+ jsondec_skipval(d);
+ }
+ jsondec_objend(d);
+ break;
+ case JD_ARRAY:
+ jsondec_arrstart(d);
+ while (jsondec_arrnext(d)) {
+ jsondec_skipval(d);
+ }
+ jsondec_arrend(d);
+ break;
+ case JD_TRUE:
+ jsondec_true(d);
+ break;
+ case JD_FALSE:
+ jsondec_false(d);
+ break;
+ case JD_NULL:
+ jsondec_null(d);
+ break;
+ case JD_STRING:
+ jsondec_string(d);
+ break;
+ case JD_NUMBER:
+ jsondec_number(d);
+ break;
+ }
+}
+
+/* Base64 decoding for bytes fields. ******************************************/
+
+static unsigned int jsondec_base64_tablelookup(const char ch) {
+ /* Table includes the normal base64 chars plus the URL-safe variant. */
+ const signed char table[256] = {
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/,
+ 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/,
+ 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1,
+ -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/,
+ 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/,
+ 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/,
+ 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/,
+ -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/,
+ 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/,
+ 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/,
+ 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/,
+ 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1};
+
+ /* Sign-extend return value so high bit will be set on any unexpected char. */
+ return table[(unsigned)ch];
+}
+
+static char* jsondec_partialbase64(jsondec* d, const char* ptr, const char* end,
+ char* out) {
+ int32_t val = -1;
+
+ switch (end - ptr) {
+ case 2:
+ val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+ jsondec_base64_tablelookup(ptr[1]) << 12;
+ out[0] = val >> 16;
+ out += 1;
+ break;
+ case 3:
+ val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+ jsondec_base64_tablelookup(ptr[1]) << 12 |
+ jsondec_base64_tablelookup(ptr[2]) << 6;
+ out[0] = val >> 16;
+ out[1] = (val >> 8) & 0xff;
+ out += 2;
+ break;
+ }
+
+ if (val < 0) {
+ jsondec_err(d, "Corrupt base64");
+ }
+
+ return out;
+}
+
+static size_t jsondec_base64(jsondec* d, upb_StringView str) {
+ /* We decode in place. This is safe because this is a new buffer (not
+ * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */
+ char* out = (char*)str.data;
+ const char* ptr = str.data;
+ const char* end = ptr + str.size;
+ const char* end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */
+
+ for (; ptr < end4; ptr += 4, out += 3) {
+ int val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+ jsondec_base64_tablelookup(ptr[1]) << 12 |
+ jsondec_base64_tablelookup(ptr[2]) << 6 |
+ jsondec_base64_tablelookup(ptr[3]) << 0;
+
+ if (val < 0) {
+ /* Junk chars or padding. Remove trailing padding, if any. */
+ if (end - ptr == 4 && ptr[3] == '=') {
+ if (ptr[2] == '=') {
+ end -= 2;
+ } else {
+ end -= 1;
+ }
+ }
+ break;
+ }
+
+ out[0] = val >> 16;
+ out[1] = (val >> 8) & 0xff;
+ out[2] = val & 0xff;
+ }
+
+ if (ptr < end) {
+ /* Process remaining chars. We do not require padding. */
+ out = jsondec_partialbase64(d, ptr, end, out);
+ }
+
+ return out - str.data;
+}
+
+/* Low-level integer parsing **************************************************/
+
+/* We use these hand-written routines instead of strto[u]l() because the "long
+ * long" variants aren't in c89. Also our version allows setting a ptr limit. */
+
+static const char* jsondec_buftouint64(jsondec* d, const char* ptr,
+ const char* end, uint64_t* val) {
+ uint64_t u64 = 0;
+ while (ptr < end) {
+ unsigned ch = *ptr - '0';
+ if (ch >= 10) break;
+ if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
+ jsondec_err(d, "Integer overflow");
+ }
+ u64 *= 10;
+ u64 += ch;
+ ptr++;
+ }
+
+ *val = u64;
+ return ptr;
+}
+
+static const char* jsondec_buftoint64(jsondec* d, const char* ptr,
+ const char* end, int64_t* val) {
+ bool neg = false;
+ uint64_t u64;
+
+ if (ptr != end && *ptr == '-') {
+ ptr++;
+ neg = true;
+ }
+
+ ptr = jsondec_buftouint64(d, ptr, end, &u64);
+ if (u64 > (uint64_t)INT64_MAX + neg) {
+ jsondec_err(d, "Integer overflow");
+ }
+
+ *val = neg ? -u64 : u64;
+ return ptr;
+}
+
+static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) {
+ const char* end = str.data + str.size;
+ uint64_t ret;
+ if (jsondec_buftouint64(d, str.data, end, &ret) != end) {
+ jsondec_err(d, "Non-number characters in quoted integer");
+ }
+ return ret;
+}
+
+static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) {
+ const char* end = str.data + str.size;
+ int64_t ret;
+ if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+ jsondec_err(d, "Non-number characters in quoted integer");
+ }
+ return ret;
+}
+
+/* Primitive value types ******************************************************/
+
+/* Parse INT32 or INT64 value. */
+static upb_MessageValue jsondec_int(jsondec* d, const upb_FieldDef* f) {
+ upb_MessageValue val;
+
+ switch (jsondec_peek(d)) {
+ case JD_NUMBER: {
+ double dbl = jsondec_number(d);
+ if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
+ jsondec_err(d, "JSON number is out of range.");
+ }
+ val.int64_val = dbl; /* must be guarded, overflow here is UB */
+ if (val.int64_val != dbl) {
+ jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl,
+ val.int64_val);
+ }
+ break;
+ }
+ case JD_STRING: {
+ upb_StringView str = jsondec_string(d);
+ val.int64_val = jsondec_strtoint64(d, str);
+ break;
+ }
+ default:
+ jsondec_err(d, "Expected number or string");
+ }
+
+ if (upb_FieldDef_CType(f) == kUpb_CType_Int32 ||
+ upb_FieldDef_CType(f) == kUpb_CType_Enum) {
+ if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) {
+ jsondec_err(d, "Integer out of range.");
+ }
+ val.int32_val = (int32_t)val.int64_val;
+ }
+
+ return val;
+}
+
+/* Parse UINT32 or UINT64 value. */
+static upb_MessageValue jsondec_uint(jsondec* d, const upb_FieldDef* f) {
+ upb_MessageValue val = {0};
+
+ switch (jsondec_peek(d)) {
+ case JD_NUMBER: {
+ double dbl = jsondec_number(d);
+ if (dbl > 18446744073709549568.0 || dbl < 0) {
+ jsondec_err(d, "JSON number is out of range.");
+ }
+ val.uint64_val = dbl; /* must be guarded, overflow here is UB */
+ if (val.uint64_val != dbl) {
+ jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl,
+ val.uint64_val);
+ }
+ break;
+ }
+ case JD_STRING: {
+ upb_StringView str = jsondec_string(d);
+ val.uint64_val = jsondec_strtouint64(d, str);
+ break;
+ }
+ default:
+ jsondec_err(d, "Expected number or string");
+ }
+
+ if (upb_FieldDef_CType(f) == kUpb_CType_UInt32) {
+ if (val.uint64_val > UINT32_MAX) {
+ jsondec_err(d, "Integer out of range.");
+ }
+ val.uint32_val = (uint32_t)val.uint64_val;
+ }
+
+ return val;
+}
+
+/* Parse DOUBLE or FLOAT value. */
+static upb_MessageValue jsondec_double(jsondec* d, const upb_FieldDef* f) {
+ upb_StringView str;
+ upb_MessageValue val = {0};
+
+ switch (jsondec_peek(d)) {
+ case JD_NUMBER:
+ val.double_val = jsondec_number(d);
+ break;
+ case JD_STRING:
+ str = jsondec_string(d);
+ if (jsondec_streql(str, "NaN")) {
+ val.double_val = NAN;
+ } else if (jsondec_streql(str, "Infinity")) {
+ val.double_val = INFINITY;
+ } else if (jsondec_streql(str, "-Infinity")) {
+ val.double_val = -INFINITY;
+ } else {
+ val.double_val = strtod(str.data, NULL);
+ }
+ break;
+ default:
+ jsondec_err(d, "Expected number or string");
+ }
+
+ if (upb_FieldDef_CType(f) == kUpb_CType_Float) {
+ if (val.double_val != INFINITY && val.double_val != -INFINITY &&
+ (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) {
+ jsondec_err(d, "Float out of range");
+ }
+ val.float_val = val.double_val;
+ }
+
+ return val;
+}
+
+/* Parse STRING or BYTES value. */
+static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) {
+ upb_MessageValue val;
+ val.str_val = jsondec_string(d);
+ if (upb_FieldDef_CType(f) == kUpb_CType_Bytes) {
+ val.str_val.size = jsondec_base64(d, val.str_val);
+ }
+ return val;
+}
+
+static upb_MessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) {
+ switch (jsondec_peek(d)) {
+ case JD_STRING: {
+ upb_StringView str = jsondec_string(d);
+ const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f);
+ const upb_EnumValueDef* ev =
+ upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size);
+ upb_MessageValue val;
+ if (ev) {
+ val.int32_val = upb_EnumValueDef_Number(ev);
+ } else {
+ if (d->options & upb_JsonDecode_IgnoreUnknown) {
+ val.int32_val = 0;
+ } else {
+ jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'",
+ UPB_STRINGVIEW_ARGS(str));
+ }
+ }
+ return val;
+ }
+ case JD_NULL: {
+ if (jsondec_isnullvalue(f)) {
+ upb_MessageValue val;
+ jsondec_null(d);
+ val.int32_val = 0;
+ return val;
+ }
+ }
+ /* Fallthrough. */
+ default:
+ return jsondec_int(d, f);
+ }
+}
+
+static upb_MessageValue jsondec_bool(jsondec* d, const upb_FieldDef* f) {
+ bool is_map_key = upb_FieldDef_Number(f) == 1 &&
+ upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f));
+ upb_MessageValue val;
+
+ if (is_map_key) {
+ upb_StringView str = jsondec_string(d);
+ if (jsondec_streql(str, "true")) {
+ val.bool_val = true;
+ } else if (jsondec_streql(str, "false")) {
+ val.bool_val = false;
+ } else {
+ jsondec_err(d, "Invalid boolean map key");
+ }
+ } else {
+ switch (jsondec_peek(d)) {
+ case JD_TRUE:
+ val.bool_val = true;
+ jsondec_true(d);
+ break;
+ case JD_FALSE:
+ val.bool_val = false;
+ jsondec_false(d);
+ break;
+ default:
+ jsondec_err(d, "Expected true or false");
+ }
+ }
+
+ return val;
+}
+
+/* Composite types (array/message/map) ****************************************/
+
+static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) {
+ upb_Array* arr = upb_Message_Mutable(msg, f, d->arena).array;
+
+ jsondec_arrstart(d);
+ while (jsondec_arrnext(d)) {
+ upb_MessageValue elem = jsondec_value(d, f);
+ upb_Array_Append(arr, elem, d->arena);
+ }
+ jsondec_arrend(d);
+}
+
+static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) {
+ upb_Map* map = upb_Message_Mutable(msg, f, d->arena).map;
+ const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
+ const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1);
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2);
+
+ jsondec_objstart(d);
+ while (jsondec_objnext(d)) {
+ upb_MessageValue key, val;
+ key = jsondec_value(d, key_f);
+ jsondec_entrysep(d);
+ val = jsondec_value(d, val_f);
+ upb_Map_Set(map, key, val, d->arena);
+ }
+ jsondec_objend(d);
+}
+
+static void jsondec_tomsg(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) {
+ jsondec_object(d, msg, m);
+ } else {
+ jsondec_wellknown(d, msg, m);
+ }
+}
+
+static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) {
+ const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
+ upb_Message* msg = upb_Message_New(m, d->arena);
+ upb_MessageValue val;
+
+ jsondec_tomsg(d, msg, m);
+ val.msg_val = msg;
+ return val;
+}
+
+static void jsondec_field(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ upb_StringView name;
+ const upb_FieldDef* f;
+ const upb_FieldDef* preserved;
+
+ name = jsondec_string(d);
+ jsondec_entrysep(d);
+
+ if (name.size >= 2 && name.data[0] == '[' &&
+ name.data[name.size - 1] == ']') {
+ f = upb_DefPool_FindExtensionByNameWithSize(d->symtab, name.data + 1,
+ name.size - 2);
+ if (f && upb_FieldDef_ContainingType(f) != m) {
+ jsondec_errf(
+ d, "Extension %s extends message %s, but was seen in message %s",
+ upb_FieldDef_FullName(f),
+ upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)),
+ upb_MessageDef_FullName(m));
+ }
+ } else {
+ f = upb_MessageDef_FindByJsonNameWithSize(m, name.data, name.size);
+ }
+
+ if (!f) {
+ if ((d->options & upb_JsonDecode_IgnoreUnknown) == 0) {
+ jsondec_errf(d, "No such field: " UPB_STRINGVIEW_FORMAT,
+ UPB_STRINGVIEW_ARGS(name));
+ }
+ jsondec_skipval(d);
+ return;
+ }
+
+ if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) {
+ /* JSON "null" indicates a default value, so no need to set anything. */
+ jsondec_null(d);
+ return;
+ }
+
+ if (upb_FieldDef_RealContainingOneof(f) &&
+ upb_Message_WhichOneof(msg, upb_FieldDef_ContainingOneof(f))) {
+ jsondec_err(d, "More than one field for this oneof.");
+ }
+
+ preserved = d->debug_field;
+ d->debug_field = f;
+
+ if (upb_FieldDef_IsMap(f)) {
+ jsondec_map(d, msg, f);
+ } else if (upb_FieldDef_IsRepeated(f)) {
+ jsondec_array(d, msg, f);
+ } else if (upb_FieldDef_IsSubMessage(f)) {
+ upb_Message* submsg = upb_Message_Mutable(msg, f, d->arena).msg;
+ const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
+ jsondec_tomsg(d, submsg, subm);
+ } else {
+ upb_MessageValue val = jsondec_value(d, f);
+ upb_Message_Set(msg, f, val, d->arena);
+ }
+
+ d->debug_field = preserved;
+}
+
+static void jsondec_object(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ jsondec_objstart(d);
+ while (jsondec_objnext(d)) {
+ jsondec_field(d, msg, m);
+ }
+ jsondec_objend(d);
+}
+
+static upb_MessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) {
+ switch (upb_FieldDef_CType(f)) {
+ case kUpb_CType_Bool:
+ return jsondec_bool(d, f);
+ case kUpb_CType_Float:
+ case kUpb_CType_Double:
+ return jsondec_double(d, f);
+ case kUpb_CType_UInt32:
+ case kUpb_CType_UInt64:
+ return jsondec_uint(d, f);
+ case kUpb_CType_Int32:
+ case kUpb_CType_Int64:
+ return jsondec_int(d, f);
+ case kUpb_CType_String:
+ case kUpb_CType_Bytes:
+ return jsondec_strfield(d, f);
+ case kUpb_CType_Enum:
+ return jsondec_enum(d, f);
+ case kUpb_CType_Message:
+ return jsondec_msg(d, f);
+ default:
+ UPB_UNREACHABLE();
+ }
+}
+
+/* Well-known types ***********************************************************/
+
+static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits,
+ const char* after) {
+ uint64_t val;
+ const char* p = *ptr;
+ const char* end = p + digits;
+ size_t after_len = after ? strlen(after) : 0;
+
+ UPB_ASSERT(digits <= 9); /* int can't overflow. */
+
+ if (jsondec_buftouint64(d, p, end, &val) != end ||
+ (after_len && memcmp(end, after, after_len) != 0)) {
+ jsondec_err(d, "Malformed timestamp");
+ }
+
+ UPB_ASSERT(val < INT_MAX);
+
+ *ptr = end + after_len;
+ return (int)val;
+}
+
+static int jsondec_nanos(jsondec* d, const char** ptr, const char* end) {
+ uint64_t nanos = 0;
+ const char* p = *ptr;
+
+ if (p != end && *p == '.') {
+ const char* nano_end = jsondec_buftouint64(d, p + 1, end, &nanos);
+ int digits = (int)(nano_end - p - 1);
+ int exp_lg10 = 9 - digits;
+ if (digits > 9) {
+ jsondec_err(d, "Too many digits for partial seconds");
+ }
+ while (exp_lg10--) nanos *= 10;
+ *ptr = nano_end;
+ }
+
+ UPB_ASSERT(nanos < INT_MAX);
+
+ return (int)nanos;
+}
+
+/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */
+int jsondec_epochdays(int y, int m, int d) {
+ const uint32_t year_base = 4800; /* Before min year, multiple of 400. */
+ const uint32_t m_adj = m - 3; /* March-based month. */
+ const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0;
+ const uint32_t adjust = carry ? 12 : 0;
+ const uint32_t y_adj = y + year_base - carry;
+ const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048;
+ const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400;
+ return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632;
+}
+
+static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) {
+ return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s;
+}
+
+static void jsondec_timestamp(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ upb_MessageValue seconds;
+ upb_MessageValue nanos;
+ upb_StringView str = jsondec_string(d);
+ const char* ptr = str.data;
+ const char* end = ptr + str.size;
+
+ if (str.size < 20) goto malformed;
+
+ {
+ /* 1972-01-01T01:00:00 */
+ int year = jsondec_tsdigits(d, &ptr, 4, "-");
+ int mon = jsondec_tsdigits(d, &ptr, 2, "-");
+ int day = jsondec_tsdigits(d, &ptr, 2, "T");
+ int hour = jsondec_tsdigits(d, &ptr, 2, ":");
+ int min = jsondec_tsdigits(d, &ptr, 2, ":");
+ int sec = jsondec_tsdigits(d, &ptr, 2, NULL);
+
+ seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec);
+ }
+
+ nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+ {
+ /* [+-]08:00 or Z */
+ int ofs_hour = 0;
+ int ofs_min = 0;
+ bool neg = false;
+
+ if (ptr == end) goto malformed;
+
+ switch (*ptr++) {
+ case '-':
+ neg = true;
+ /* fallthrough */
+ case '+':
+ if ((end - ptr) != 5) goto malformed;
+ ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":");
+ ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL);
+ ofs_min = ((ofs_hour * 60) + ofs_min) * 60;
+ seconds.int64_val += (neg ? ofs_min : -ofs_min);
+ break;
+ case 'Z':
+ if (ptr != end) goto malformed;
+ break;
+ default:
+ goto malformed;
+ }
+ }
+
+ if (seconds.int64_val < -62135596800) {
+ jsondec_err(d, "Timestamp out of range");
+ }
+
+ upb_Message_Set(msg, upb_MessageDef_FindFieldByNumber(m, 1), seconds,
+ d->arena);
+ upb_Message_Set(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, d->arena);
+ return;
+
+malformed:
+ jsondec_err(d, "Malformed timestamp");
+}
+
+static void jsondec_duration(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ upb_MessageValue seconds;
+ upb_MessageValue nanos;
+ upb_StringView str = jsondec_string(d);
+ const char* ptr = str.data;
+ const char* end = ptr + str.size;
+ const int64_t max = (uint64_t)3652500 * 86400;
+
+ /* "3.000000001s", "3s", etc. */
+ ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+ nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+ if (end - ptr != 1 || *ptr != 's') {
+ jsondec_err(d, "Malformed duration");
+ }
+
+ if (seconds.int64_val < -max || seconds.int64_val > max) {
+ jsondec_err(d, "Duration out of range");
+ }
+
+ if (seconds.int64_val < 0) {
+ nanos.int32_val = -nanos.int32_val;
+ }
+
+ upb_Message_Set(msg, upb_MessageDef_FindFieldByNumber(m, 1), seconds,
+ d->arena);
+ upb_Message_Set(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, d->arena);
+}
+
+static void jsondec_listvalue(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f);
+ upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array;
+
+ jsondec_arrstart(d);
+ while (jsondec_arrnext(d)) {
+ upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+ upb_MessageValue value;
+ value.msg_val = value_msg;
+ upb_Array_Append(values, value, d->arena);
+ jsondec_wellknownvalue(d, value_msg, value_m);
+ }
+ jsondec_arrend(d);
+}
+
+static void jsondec_struct(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
+ const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
+ const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f);
+ upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map;
+
+ jsondec_objstart(d);
+ while (jsondec_objnext(d)) {
+ upb_MessageValue key, value;
+ upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+ key.str_val = jsondec_string(d);
+ value.msg_val = value_msg;
+ upb_Map_Set(fields, key, value, d->arena);
+ jsondec_entrysep(d);
+ jsondec_wellknownvalue(d, value_msg, value_m);
+ }
+ jsondec_objend(d);
+}
+
+static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ upb_MessageValue val;
+ const upb_FieldDef* f;
+ upb_Message* submsg;
+
+ switch (jsondec_peek(d)) {
+ case JD_NUMBER:
+ /* double number_value = 2; */
+ f = upb_MessageDef_FindFieldByNumber(m, 2);
+ val.double_val = jsondec_number(d);
+ break;
+ case JD_STRING:
+ /* string string_value = 3; */
+ f = upb_MessageDef_FindFieldByNumber(m, 3);
+ val.str_val = jsondec_string(d);
+ break;
+ case JD_FALSE:
+ /* bool bool_value = 4; */
+ f = upb_MessageDef_FindFieldByNumber(m, 4);
+ val.bool_val = false;
+ jsondec_false(d);
+ break;
+ case JD_TRUE:
+ /* bool bool_value = 4; */
+ f = upb_MessageDef_FindFieldByNumber(m, 4);
+ val.bool_val = true;
+ jsondec_true(d);
+ break;
+ case JD_NULL:
+ /* NullValue null_value = 1; */
+ f = upb_MessageDef_FindFieldByNumber(m, 1);
+ val.int32_val = 0;
+ jsondec_null(d);
+ break;
+ /* Note: these cases return, because upb_Message_Mutable() is enough. */
+ case JD_OBJECT:
+ /* Struct struct_value = 5; */
+ f = upb_MessageDef_FindFieldByNumber(m, 5);
+ submsg = upb_Message_Mutable(msg, f, d->arena).msg;
+ jsondec_struct(d, submsg, upb_FieldDef_MessageSubDef(f));
+ return;
+ case JD_ARRAY:
+ /* ListValue list_value = 6; */
+ f = upb_MessageDef_FindFieldByNumber(m, 6);
+ submsg = upb_Message_Mutable(msg, f, d->arena).msg;
+ jsondec_listvalue(d, submsg, upb_FieldDef_MessageSubDef(f));
+ return;
+ default:
+ UPB_UNREACHABLE();
+ }
+
+ upb_Message_Set(msg, f, val, d->arena);
+}
+
+static upb_StringView jsondec_mask(jsondec* d, const char* buf,
+ const char* end) {
+ /* FieldMask fields grow due to inserted '_' characters, so we can't do the
+ * transform in place. */
+ const char* ptr = buf;
+ upb_StringView ret;
+ char* out;
+
+ ret.size = end - ptr;
+ while (ptr < end) {
+ ret.size += (*ptr >= 'A' && *ptr <= 'Z');
+ ptr++;
+ }
+
+ out = upb_Arena_Malloc(d->arena, ret.size);
+ ptr = buf;
+ ret.data = out;
+
+ while (ptr < end) {
+ char ch = *ptr++;
+ if (ch >= 'A' && ch <= 'Z') {
+ *out++ = '_';
+ *out++ = ch + 32;
+ } else if (ch == '_') {
+ jsondec_err(d, "field mask may not contain '_'");
+ } else {
+ *out++ = ch;
+ }
+ }
+
+ return ret;
+}
+
+static void jsondec_fieldmask(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ /* repeated string paths = 1; */
+ const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ upb_Array* arr = upb_Message_Mutable(msg, paths_f, d->arena).array;
+ upb_StringView str = jsondec_string(d);
+ const char* ptr = str.data;
+ const char* end = ptr + str.size;
+ upb_MessageValue val;
+
+ while (ptr < end) {
+ const char* elem_end = memchr(ptr, ',', end - ptr);
+ if (elem_end) {
+ val.str_val = jsondec_mask(d, ptr, elem_end);
+ ptr = elem_end + 1;
+ } else {
+ val.str_val = jsondec_mask(d, ptr, end);
+ ptr = end;
+ }
+ upb_Array_Append(arr, val, d->arena);
+ }
+}
+
+static void jsondec_anyfield(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) {
+ /* For regular types: {"@type": "[user type]", "f1": <V1>, "f2": <V2>}
+ * where f1, f2, etc. are the normal fields of this type. */
+ jsondec_field(d, msg, m);
+ } else {
+ /* For well-known types: {"@type": "[well-known type]", "value": <X>}
+ * where <X> is whatever encoding the WKT normally uses. */
+ upb_StringView str = jsondec_string(d);
+ jsondec_entrysep(d);
+ if (!jsondec_streql(str, "value")) {
+ jsondec_err(d, "Key for well-known type must be 'value'");
+ }
+ jsondec_wellknown(d, msg, m);
+ }
+}
+
+static const upb_MessageDef* jsondec_typeurl(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_MessageDef* type_m;
+ upb_StringView type_url = jsondec_string(d);
+ const char* end = type_url.data + type_url.size;
+ const char* ptr = end;
+ upb_MessageValue val;
+
+ val.str_val = type_url;
+ upb_Message_Set(msg, type_url_f, val, d->arena);
+
+ /* Find message name after the last '/' */
+ while (ptr > type_url.data && *--ptr != '/') {
+ }
+
+ if (ptr == type_url.data || ptr == end) {
+ jsondec_err(d, "Type url must have at least one '/' and non-empty host");
+ }
+
+ ptr++;
+ type_m = upb_DefPool_FindMessageByNameWithSize(d->symtab, ptr, end - ptr);
+
+ if (!type_m) {
+ jsondec_err(d, "Type was not found");
+ }
+
+ return type_m;
+}
+
+static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) {
+ /* string type_url = 1;
+ * bytes value = 2; */
+ const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2);
+ upb_Message* any_msg;
+ const upb_MessageDef* any_m = NULL;
+ const char* pre_type_data = NULL;
+ const char* pre_type_end = NULL;
+ upb_MessageValue encoded;
+
+ jsondec_objstart(d);
+
+ /* Scan looking for "@type", which is not necessarily first. */
+ while (!any_m && jsondec_objnext(d)) {
+ const char* start = d->ptr;
+ upb_StringView name = jsondec_string(d);
+ jsondec_entrysep(d);
+ if (jsondec_streql(name, "@type")) {
+ any_m = jsondec_typeurl(d, msg, m);
+ if (pre_type_data) {
+ pre_type_end = start;
+ while (*pre_type_end != ',') pre_type_end--;
+ }
+ } else {
+ if (!pre_type_data) pre_type_data = start;
+ jsondec_skipval(d);
+ }
+ }
+
+ if (!any_m) {
+ jsondec_err(d, "Any object didn't contain a '@type' field");
+ }
+
+ any_msg = upb_Message_New(any_m, d->arena);
+
+ if (pre_type_data) {
+ size_t len = pre_type_end - pre_type_data + 1;
+ char* tmp = upb_Arena_Malloc(d->arena, len);
+ const char* saved_ptr = d->ptr;
+ const char* saved_end = d->end;
+ memcpy(tmp, pre_type_data, len - 1);
+ tmp[len - 1] = '}';
+ d->ptr = tmp;
+ d->end = tmp + len;
+ d->is_first = true;
+ while (jsondec_objnext(d)) {
+ jsondec_anyfield(d, any_msg, any_m);
+ }
+ d->ptr = saved_ptr;
+ d->end = saved_end;
+ }
+
+ while (jsondec_objnext(d)) {
+ jsondec_anyfield(d, any_msg, any_m);
+ }
+
+ jsondec_objend(d);
+
+ upb_EncodeStatus status =
+ upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena,
+ (char**)&encoded.str_val.data, &encoded.str_val.size);
+ // TODO(b/235839510): We should fail gracefully here on a bad return status.
+ UPB_ASSERT(status == kUpb_EncodeStatus_Ok);
+ upb_Message_Set(msg, value_f, encoded, d->arena);
+}
+
+static void jsondec_wrapper(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ upb_MessageValue val = jsondec_value(d, value_f);
+ upb_Message_Set(msg, value_f, val, d->arena);
+}
+
+static void jsondec_wellknown(jsondec* d, upb_Message* msg,
+ const upb_MessageDef* m) {
+ switch (upb_MessageDef_WellKnownType(m)) {
+ case kUpb_WellKnown_Any:
+ jsondec_any(d, msg, m);
+ break;
+ case kUpb_WellKnown_FieldMask:
+ jsondec_fieldmask(d, msg, m);
+ break;
+ case kUpb_WellKnown_Duration:
+ jsondec_duration(d, msg, m);
+ break;
+ case kUpb_WellKnown_Timestamp:
+ jsondec_timestamp(d, msg, m);
+ break;
+ case kUpb_WellKnown_Value:
+ jsondec_wellknownvalue(d, msg, m);
+ break;
+ case kUpb_WellKnown_ListValue:
+ jsondec_listvalue(d, msg, m);
+ break;
+ case kUpb_WellKnown_Struct:
+ jsondec_struct(d, msg, m);
+ break;
+ case kUpb_WellKnown_DoubleValue:
+ case kUpb_WellKnown_FloatValue:
+ case kUpb_WellKnown_Int64Value:
+ case kUpb_WellKnown_UInt64Value:
+ case kUpb_WellKnown_Int32Value:
+ case kUpb_WellKnown_UInt32Value:
+ case kUpb_WellKnown_StringValue:
+ case kUpb_WellKnown_BytesValue:
+ case kUpb_WellKnown_BoolValue:
+ jsondec_wrapper(d, msg, m);
+ break;
+ default:
+ UPB_UNREACHABLE();
+ }
+}
+
+bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
+ const upb_MessageDef* m, const upb_DefPool* symtab,
+ int options, upb_Arena* arena, upb_Status* status) {
+ jsondec d;
+
+ if (size == 0) return true;
+
+ d.ptr = buf;
+ d.end = buf + size;
+ d.arena = arena;
+ d.symtab = symtab;
+ d.status = status;
+ d.options = options;
+ d.depth = 64;
+ d.line = 1;
+ d.line_begin = d.ptr;
+ d.debug_field = NULL;
+ d.is_first = false;
+
+ if (UPB_SETJMP(d.err)) return false;
+
+ jsondec_tomsg(&d, msg, m);
+ return true;
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/json_decode.h b/contrib/libs/grpc/third_party/upb/upb/json_decode.h
new file mode 100644
index 0000000000..848f4df33c
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/json_decode.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_JSONDECODE_H_
+#define UPB_JSONDECODE_H_
+
+#include "upb/def.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum { upb_JsonDecode_IgnoreUnknown = 1 };
+
+bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
+ const upb_MessageDef* m, const upb_DefPool* symtab,
+ int options, upb_Arena* arena, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_JSONDECODE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/json_encode.c b/contrib/libs/grpc/third_party/upb/upb/json_encode.c
new file mode 100644
index 0000000000..e13c0f771d
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/json_encode.c
@@ -0,0 +1,780 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/json_encode.h"
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "upb/decode.h"
+#include "upb/internal/upb.h"
+#include "upb/internal/vsnprintf_compat.h"
+#include "upb/reflection.h"
+
+/* Must be last. */
+#include "upb/port_def.inc"
+
+typedef struct {
+ char *buf, *ptr, *end;
+ size_t overflow;
+ int indent_depth;
+ int options;
+ const upb_DefPool* ext_pool;
+ jmp_buf err;
+ upb_Status* status;
+ upb_Arena* arena;
+} jsonenc;
+
+static void jsonenc_msg(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m);
+static void jsonenc_scalar(jsonenc* e, upb_MessageValue val,
+ const upb_FieldDef* f);
+static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m);
+static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m, bool first);
+static void jsonenc_value(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m);
+
+UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) {
+ upb_Status_SetErrorMessage(e->status, msg);
+ longjmp(e->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ upb_Status_VSetErrorFormat(e->status, fmt, argp);
+ va_end(argp);
+ longjmp(e->err, 1);
+}
+
+static upb_Arena* jsonenc_arena(jsonenc* e) {
+ /* Create lazily, since it's only needed for Any */
+ if (!e->arena) {
+ e->arena = upb_Arena_New();
+ }
+ return e->arena;
+}
+
+static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) {
+ size_t have = e->end - e->ptr;
+ if (UPB_LIKELY(have >= len)) {
+ memcpy(e->ptr, data, len);
+ e->ptr += len;
+ } else {
+ if (have) {
+ memcpy(e->ptr, data, have);
+ e->ptr += have;
+ }
+ e->overflow += (len - have);
+ }
+}
+
+static void jsonenc_putstr(jsonenc* e, const char* str) {
+ jsonenc_putbytes(e, str, strlen(str));
+}
+
+UPB_PRINTF(2, 3)
+static void jsonenc_printf(jsonenc* e, const char* fmt, ...) {
+ size_t n;
+ size_t have = e->end - e->ptr;
+ va_list args;
+
+ va_start(args, fmt);
+ n = _upb_vsnprintf(e->ptr, have, fmt, args);
+ va_end(args);
+
+ if (UPB_LIKELY(have > n)) {
+ e->ptr += n;
+ } else {
+ e->ptr = UPB_PTRADD(e->ptr, have);
+ e->overflow += (n - have);
+ }
+}
+
+static void jsonenc_nanos(jsonenc* e, int32_t nanos) {
+ int digits = 9;
+
+ if (nanos == 0) return;
+ if (nanos < 0 || nanos >= 1000000000) {
+ jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos");
+ }
+
+ while (nanos % 1000 == 0) {
+ nanos /= 1000;
+ digits -= 3;
+ }
+
+ jsonenc_printf(e, ".%.*" PRId32, digits, nanos);
+}
+
+static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
+ int64_t seconds = upb_Message_Get(msg, seconds_f).int64_val;
+ int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
+ int L, N, I, J, K, hour, min, sec;
+
+ if (seconds < -62135596800) {
+ jsonenc_err(e,
+ "error formatting timestamp as JSON: minimum acceptable value "
+ "is 0001-01-01T00:00:00Z");
+ } else if (seconds > 253402300799) {
+ jsonenc_err(e,
+ "error formatting timestamp as JSON: maximum acceptable value "
+ "is 9999-12-31T23:59:59Z");
+ }
+
+ /* Julian Day -> Y/M/D, Algorithm from:
+ * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
+ * Processing Calendar Dates," Communications of the Association of
+ * Computing Machines, vol. 11 (1968), p. 657. */
+ seconds += 62135596800; // Ensure seconds is positive.
+ L = (int)(seconds / 86400) - 719162 + 68569 + 2440588;
+ N = 4 * L / 146097;
+ L = L - (146097 * N + 3) / 4;
+ I = 4000 * (L + 1) / 1461001;
+ L = L - 1461 * I / 4 + 31;
+ J = 80 * L / 2447;
+ K = L - 2447 * J / 80;
+ L = J / 11;
+ J = J + 2 - 12 * L;
+ I = 100 * (N - 49) + I + L;
+
+ sec = seconds % 60;
+ min = (seconds / 60) % 60;
+ hour = (seconds / 3600) % 24;
+
+ jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec);
+ jsonenc_nanos(e, nanos);
+ jsonenc_putstr(e, "Z\"");
+}
+
+static void jsonenc_duration(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
+ int64_t seconds = upb_Message_Get(msg, seconds_f).int64_val;
+ int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
+
+ if (seconds > 315576000000 || seconds < -315576000000 ||
+ (seconds < 0) != (nanos < 0)) {
+ jsonenc_err(e, "bad duration");
+ }
+
+ if (nanos < 0) {
+ nanos = -nanos;
+ }
+
+ jsonenc_printf(e, "\"%" PRId64, seconds);
+ jsonenc_nanos(e, nanos);
+ jsonenc_putstr(e, "s\"");
+}
+
+static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) {
+ const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f);
+
+ if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) {
+ jsonenc_putstr(e, "null");
+ } else {
+ const upb_EnumValueDef* ev =
+ (e->options & upb_JsonEncode_FormatEnumsAsIntegers)
+ ? NULL
+ : upb_EnumDef_FindValueByNumber(e_def, val);
+
+ if (ev) {
+ jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev));
+ } else {
+ jsonenc_printf(e, "%" PRId32, val);
+ }
+ }
+}
+
+static void jsonenc_bytes(jsonenc* e, upb_StringView str) {
+ /* This is the regular base64, not the "web-safe" version. */
+ static const char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ const unsigned char* ptr = (unsigned char*)str.data;
+ const unsigned char* end = UPB_PTRADD(ptr, str.size);
+ char buf[4];
+
+ jsonenc_putstr(e, "\"");
+
+ while (end - ptr >= 3) {
+ buf[0] = base64[ptr[0] >> 2];
+ buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+ buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)];
+ buf[3] = base64[ptr[2] & 0x3f];
+ jsonenc_putbytes(e, buf, 4);
+ ptr += 3;
+ }
+
+ switch (end - ptr) {
+ case 2:
+ buf[0] = base64[ptr[0] >> 2];
+ buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+ buf[2] = base64[(ptr[1] & 0xf) << 2];
+ buf[3] = '=';
+ jsonenc_putbytes(e, buf, 4);
+ break;
+ case 1:
+ buf[0] = base64[ptr[0] >> 2];
+ buf[1] = base64[((ptr[0] & 0x3) << 4)];
+ buf[2] = '=';
+ buf[3] = '=';
+ jsonenc_putbytes(e, buf, 4);
+ break;
+ }
+
+ jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_stringbody(jsonenc* e, upb_StringView str) {
+ const char* ptr = str.data;
+ const char* end = UPB_PTRADD(ptr, str.size);
+
+ while (ptr < end) {
+ switch (*ptr) {
+ case '\n':
+ jsonenc_putstr(e, "\\n");
+ break;
+ case '\r':
+ jsonenc_putstr(e, "\\r");
+ break;
+ case '\t':
+ jsonenc_putstr(e, "\\t");
+ break;
+ case '\"':
+ jsonenc_putstr(e, "\\\"");
+ break;
+ case '\f':
+ jsonenc_putstr(e, "\\f");
+ break;
+ case '\b':
+ jsonenc_putstr(e, "\\b");
+ break;
+ case '\\':
+ jsonenc_putstr(e, "\\\\");
+ break;
+ default:
+ if ((uint8_t)*ptr < 0x20) {
+ jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
+ } else {
+ /* This could be a non-ASCII byte. We rely on the string being valid
+ * UTF-8. */
+ jsonenc_putbytes(e, ptr, 1);
+ }
+ break;
+ }
+ ptr++;
+ }
+}
+
+static void jsonenc_string(jsonenc* e, upb_StringView str) {
+ jsonenc_putstr(e, "\"");
+ jsonenc_stringbody(e, str);
+ jsonenc_putstr(e, "\"");
+}
+
+static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) {
+ if (val == INFINITY) {
+ jsonenc_putstr(e, "\"Infinity\"");
+ } else if (val == -INFINITY) {
+ jsonenc_putstr(e, "\"-Infinity\"");
+ } else if (val != val) {
+ jsonenc_putstr(e, "\"NaN\"");
+ } else {
+ return false;
+ }
+ return true;
+}
+
+static void upb_JsonEncode_Double(jsonenc* e, double val) {
+ if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
+ char buf[32];
+ _upb_EncodeRoundTripDouble(val, buf, sizeof(buf));
+ jsonenc_putstr(e, buf);
+}
+
+static void upb_JsonEncode_Float(jsonenc* e, float val) {
+ if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
+ char buf[32];
+ _upb_EncodeRoundTripFloat(val, buf, sizeof(buf));
+ jsonenc_putstr(e, buf);
+}
+
+static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ upb_MessageValue val = upb_Message_Get(msg, val_f);
+ jsonenc_scalar(e, val, val_f);
+}
+
+static const upb_MessageDef* jsonenc_getanymsg(jsonenc* e,
+ upb_StringView type_url) {
+ /* Find last '/', if any. */
+ const char* end = type_url.data + type_url.size;
+ const char* ptr = end;
+ const upb_MessageDef* ret;
+
+ if (!e->ext_pool) {
+ jsonenc_err(e, "Tried to encode Any, but no symtab was provided");
+ }
+
+ if (type_url.size == 0) goto badurl;
+
+ while (true) {
+ if (--ptr == type_url.data) {
+ /* Type URL must contain at least one '/', with host before. */
+ goto badurl;
+ }
+ if (*ptr == '/') {
+ ptr++;
+ break;
+ }
+ }
+
+ ret = upb_DefPool_FindMessageByNameWithSize(e->ext_pool, ptr, end - ptr);
+
+ if (!ret) {
+ jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
+ }
+
+ return ret;
+
+badurl:
+ jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT,
+ UPB_STRINGVIEW_ARGS(type_url));
+}
+
+static void jsonenc_any(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2);
+ upb_StringView type_url = upb_Message_Get(msg, type_url_f).str_val;
+ upb_StringView value = upb_Message_Get(msg, value_f).str_val;
+ const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url);
+ const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
+ upb_Arena* arena = jsonenc_arena(e);
+ upb_Message* any = upb_Message_New(any_m, arena);
+
+ if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ jsonenc_err(e, "Error decoding message in Any");
+ }
+
+ jsonenc_putstr(e, "{\"@type\":");
+ jsonenc_string(e, type_url);
+
+ if (upb_MessageDef_WellKnownType(any_m) == kUpb_WellKnown_Unspecified) {
+ /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
+ jsonenc_msgfields(e, any, any_m, false);
+ } else {
+ /* Well-known type: {"@type": "...","value": <well-known encoding>} */
+ jsonenc_putstr(e, ",\"value\":");
+ jsonenc_msgfield(e, any, any_m);
+ }
+
+ jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) {
+ if (*first) {
+ *first = false;
+ } else {
+ jsonenc_putstr(e, str);
+ }
+}
+
+static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) {
+ const char* ptr = path.data;
+ const char* end = ptr + path.size;
+
+ while (ptr < end) {
+ char ch = *ptr;
+
+ if (ch >= 'A' && ch <= 'Z') {
+ jsonenc_err(e, "Field mask element may not have upper-case letter.");
+ } else if (ch == '_') {
+ if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
+ jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
+ }
+ ch = *++ptr - 32;
+ }
+
+ jsonenc_putbytes(e, &ch, 1);
+ ptr++;
+ }
+}
+
+static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_Array* paths = upb_Message_Get(msg, paths_f).array_val;
+ bool first = true;
+ size_t i, n = 0;
+
+ if (paths) n = upb_Array_Size(paths);
+
+ jsonenc_putstr(e, "\"");
+
+ for (i = 0; i < n; i++) {
+ jsonenc_putsep(e, ",", &first);
+ jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val);
+ }
+
+ jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_struct(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
+ const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
+ size_t iter = kUpb_Map_Begin;
+ bool first = true;
+
+ jsonenc_putstr(e, "{");
+
+ if (fields) {
+ while (upb_MapIterator_Next(fields, &iter)) {
+ upb_MessageValue key = upb_MapIterator_Key(fields, iter);
+ upb_MessageValue val = upb_MapIterator_Value(fields, iter);
+
+ jsonenc_putsep(e, ",", &first);
+ jsonenc_string(e, key.str_val);
+ jsonenc_putstr(e, ":");
+ jsonenc_value(e, val.msg_val, upb_FieldDef_MessageSubDef(value_f));
+ }
+ }
+
+ jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1);
+ const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f);
+ const upb_Array* values = upb_Message_Get(msg, values_f).array_val;
+ size_t i;
+ bool first = true;
+
+ jsonenc_putstr(e, "[");
+
+ if (values) {
+ const size_t size = upb_Array_Size(values);
+ for (i = 0; i < size; i++) {
+ upb_MessageValue elem = upb_Array_Get(values, i);
+
+ jsonenc_putsep(e, ",", &first);
+ jsonenc_value(e, elem.msg_val, values_m);
+ }
+ }
+
+ jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_value(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ /* TODO(haberman): do we want a reflection method to get oneof case? */
+ size_t iter = kUpb_Message_Begin;
+ const upb_FieldDef* f;
+ upb_MessageValue val;
+
+ if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) {
+ jsonenc_err(e, "No value set in Value proto");
+ }
+
+ switch (upb_FieldDef_Number(f)) {
+ case 1:
+ jsonenc_putstr(e, "null");
+ break;
+ case 2:
+ upb_JsonEncode_Double(e, val.double_val);
+ break;
+ case 3:
+ jsonenc_string(e, val.str_val);
+ break;
+ case 4:
+ jsonenc_putstr(e, val.bool_val ? "true" : "false");
+ break;
+ case 5:
+ jsonenc_struct(e, val.msg_val, upb_FieldDef_MessageSubDef(f));
+ break;
+ case 6:
+ jsonenc_listvalue(e, val.msg_val, upb_FieldDef_MessageSubDef(f));
+ break;
+ }
+}
+
+static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ switch (upb_MessageDef_WellKnownType(m)) {
+ case kUpb_WellKnown_Unspecified:
+ jsonenc_msg(e, msg, m);
+ break;
+ case kUpb_WellKnown_Any:
+ jsonenc_any(e, msg, m);
+ break;
+ case kUpb_WellKnown_FieldMask:
+ jsonenc_fieldmask(e, msg, m);
+ break;
+ case kUpb_WellKnown_Duration:
+ jsonenc_duration(e, msg, m);
+ break;
+ case kUpb_WellKnown_Timestamp:
+ jsonenc_timestamp(e, msg, m);
+ break;
+ case kUpb_WellKnown_DoubleValue:
+ case kUpb_WellKnown_FloatValue:
+ case kUpb_WellKnown_Int64Value:
+ case kUpb_WellKnown_UInt64Value:
+ case kUpb_WellKnown_Int32Value:
+ case kUpb_WellKnown_UInt32Value:
+ case kUpb_WellKnown_StringValue:
+ case kUpb_WellKnown_BytesValue:
+ case kUpb_WellKnown_BoolValue:
+ jsonenc_wrapper(e, msg, m);
+ break;
+ case kUpb_WellKnown_Value:
+ jsonenc_value(e, msg, m);
+ break;
+ case kUpb_WellKnown_ListValue:
+ jsonenc_listvalue(e, msg, m);
+ break;
+ case kUpb_WellKnown_Struct:
+ jsonenc_struct(e, msg, m);
+ break;
+ }
+}
+
+static void jsonenc_scalar(jsonenc* e, upb_MessageValue val,
+ const upb_FieldDef* f) {
+ switch (upb_FieldDef_CType(f)) {
+ case kUpb_CType_Bool:
+ jsonenc_putstr(e, val.bool_val ? "true" : "false");
+ break;
+ case kUpb_CType_Float:
+ upb_JsonEncode_Float(e, val.float_val);
+ break;
+ case kUpb_CType_Double:
+ upb_JsonEncode_Double(e, val.double_val);
+ break;
+ case kUpb_CType_Int32:
+ jsonenc_printf(e, "%" PRId32, val.int32_val);
+ break;
+ case kUpb_CType_UInt32:
+ jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+ break;
+ case kUpb_CType_Int64:
+ jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val);
+ break;
+ case kUpb_CType_UInt64:
+ jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val);
+ break;
+ case kUpb_CType_String:
+ jsonenc_string(e, val.str_val);
+ break;
+ case kUpb_CType_Bytes:
+ jsonenc_bytes(e, val.str_val);
+ break;
+ case kUpb_CType_Enum:
+ jsonenc_enum(val.int32_val, f, e);
+ break;
+ case kUpb_CType_Message:
+ jsonenc_msgfield(e, val.msg_val, upb_FieldDef_MessageSubDef(f));
+ break;
+ }
+}
+
+static void jsonenc_mapkey(jsonenc* e, upb_MessageValue val,
+ const upb_FieldDef* f) {
+ jsonenc_putstr(e, "\"");
+
+ switch (upb_FieldDef_CType(f)) {
+ case kUpb_CType_Bool:
+ jsonenc_putstr(e, val.bool_val ? "true" : "false");
+ break;
+ case kUpb_CType_Int32:
+ jsonenc_printf(e, "%" PRId32, val.int32_val);
+ break;
+ case kUpb_CType_UInt32:
+ jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+ break;
+ case kUpb_CType_Int64:
+ jsonenc_printf(e, "%" PRId64, val.int64_val);
+ break;
+ case kUpb_CType_UInt64:
+ jsonenc_printf(e, "%" PRIu64, val.uint64_val);
+ break;
+ case kUpb_CType_String:
+ jsonenc_stringbody(e, val.str_val);
+ break;
+ default:
+ UPB_UNREACHABLE();
+ }
+
+ jsonenc_putstr(e, "\":");
+}
+
+static void jsonenc_array(jsonenc* e, const upb_Array* arr,
+ const upb_FieldDef* f) {
+ size_t i;
+ size_t size = arr ? upb_Array_Size(arr) : 0;
+ bool first = true;
+
+ jsonenc_putstr(e, "[");
+
+ for (i = 0; i < size; i++) {
+ jsonenc_putsep(e, ",", &first);
+ jsonenc_scalar(e, upb_Array_Get(arr, i), f);
+ }
+
+ jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) {
+ const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
+ const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1);
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2);
+ size_t iter = kUpb_Map_Begin;
+ bool first = true;
+
+ jsonenc_putstr(e, "{");
+
+ if (map) {
+ while (upb_MapIterator_Next(map, &iter)) {
+ jsonenc_putsep(e, ",", &first);
+ jsonenc_mapkey(e, upb_MapIterator_Key(map, iter), key_f);
+ jsonenc_scalar(e, upb_MapIterator_Value(map, iter), val_f);
+ }
+ }
+
+ jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f,
+ upb_MessageValue val, bool* first) {
+ const char* name;
+
+ jsonenc_putsep(e, ",", first);
+
+ if (upb_FieldDef_IsExtension(f)) {
+ // TODO: For MessageSet, I would have expected this to print the message
+ // name here, but Python doesn't appear to do this. We should do more
+ // research here about what various implementations do.
+ jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f));
+ } else {
+ if (e->options & upb_JsonEncode_UseProtoNames) {
+ name = upb_FieldDef_Name(f);
+ } else {
+ name = upb_FieldDef_JsonName(f);
+ }
+ jsonenc_printf(e, "\"%s\":", name);
+ }
+
+ if (upb_FieldDef_IsMap(f)) {
+ jsonenc_map(e, val.map_val, f);
+ } else if (upb_FieldDef_IsRepeated(f)) {
+ jsonenc_array(e, val.array_val, f);
+ } else {
+ jsonenc_scalar(e, val, f);
+ }
+}
+
+static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m, bool first) {
+ upb_MessageValue val;
+ const upb_FieldDef* f;
+
+ if (e->options & upb_JsonEncode_EmitDefaults) {
+ /* Iterate over all fields. */
+ int i = 0;
+ int n = upb_MessageDef_FieldCount(m);
+ for (i = 0; i < n; i++) {
+ f = upb_MessageDef_Field(m, i);
+ if (!upb_FieldDef_HasPresence(f) || upb_Message_Has(msg, f)) {
+ jsonenc_fieldval(e, f, upb_Message_Get(msg, f), &first);
+ }
+ }
+ } else {
+ /* Iterate over non-empty fields. */
+ size_t iter = kUpb_Message_Begin;
+ while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) {
+ jsonenc_fieldval(e, f, val, &first);
+ }
+ }
+}
+
+static void jsonenc_msg(jsonenc* e, const upb_Message* msg,
+ const upb_MessageDef* m) {
+ jsonenc_putstr(e, "{");
+ jsonenc_msgfields(e, msg, m, true);
+ jsonenc_putstr(e, "}");
+}
+
+static size_t jsonenc_nullz(jsonenc* e, size_t size) {
+ size_t ret = e->ptr - e->buf + e->overflow;
+
+ if (size > 0) {
+ if (e->ptr == e->end) e->ptr--;
+ *e->ptr = '\0';
+ }
+
+ return ret;
+}
+
+size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m,
+ const upb_DefPool* ext_pool, int options, char* buf,
+ size_t size, upb_Status* status) {
+ jsonenc e;
+
+ e.buf = buf;
+ e.ptr = buf;
+ e.end = UPB_PTRADD(buf, size);
+ e.overflow = 0;
+ e.options = options;
+ e.ext_pool = ext_pool;
+ e.status = status;
+ e.arena = NULL;
+
+ if (setjmp(e.err)) return -1;
+
+ jsonenc_msgfield(&e, msg, m);
+ if (e.arena) upb_Arena_Free(e.arena);
+ return jsonenc_nullz(&e, size);
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/json_encode.h b/contrib/libs/grpc/third_party/upb/upb/json_encode.h
new file mode 100644
index 0000000000..6e0cac3fc1
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/json_encode.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_JSONENCODE_H_
+#define UPB_JSONENCODE_H_
+
+#include "upb/def.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ /* When set, emits 0/default values. TODO(haberman): proto3 only? */
+ upb_JsonEncode_EmitDefaults = 1 << 0,
+
+ /* When set, use normal (snake_case) field names instead of JSON (camelCase)
+ names. */
+ upb_JsonEncode_UseProtoNames = 1 << 1,
+
+ /* When set, emits enums as their integer values instead of as their names. */
+ upb_JsonEncode_FormatEnumsAsIntegers = 1 << 2
+};
+
+/* Encodes the given |msg| to JSON format. The message's reflection is given in
+ * |m|. The symtab in |symtab| is used to find extensions (if NULL, extensions
+ * will not be printed).
+ *
+ * Output is placed in the given buffer, and always NULL-terminated. The output
+ * size (excluding NULL) is returned. This means that a return value >= |size|
+ * implies that the output was truncated. (These are the same semantics as
+ * snprintf()). */
+size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m,
+ const upb_DefPool* ext_pool, int options, char* buf,
+ size_t size, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_JSONENCODE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/map.c b/contrib/libs/grpc/third_party/upb/upb/map.c
new file mode 100644
index 0000000000..d92776f546
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/map.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/map.h"
+
+#include <string.h>
+
+#include "upb/internal/table.h"
+#include "upb/msg.h"
+#include "upb/port_def.inc"
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_CTypeo_mapsize[12] = {
+ 0,
+ 1, /* kUpb_CType_Bool */
+ 4, /* kUpb_CType_Float */
+ 4, /* kUpb_CType_Int32 */
+ 4, /* kUpb_CType_UInt32 */
+ 4, /* kUpb_CType_Enum */
+ sizeof(void*), /* kUpb_CType_Message */
+ 8, /* kUpb_CType_Double */
+ 8, /* kUpb_CType_Int64 */
+ 8, /* kUpb_CType_UInt64 */
+ 0, /* kUpb_CType_String */
+ 0, /* kUpb_CType_Bytes */
+};
+
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) {
+ return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
+ _upb_CTypeo_mapsize[value_type]);
+}
+
+size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); }
+
+bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
+ upb_MessageValue* val) {
+ return _upb_Map_Get(map, &key, map->key_size, val, map->val_size);
+}
+
+void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); }
+
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue val, upb_Arena* arena) {
+ return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val,
+ map->val_size, arena);
+}
+
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key) {
+ return _upb_Map_Delete(map, &key, map->key_size);
+}
+
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
+ return _upb_map_next(map, iter);
+}
+
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
+ upb_strtable_iter i;
+ UPB_ASSERT(iter != kUpb_Map_Begin);
+ i.t = &map->table;
+ i.index = iter;
+ return upb_strtable_done(&i);
+}
+
+/* Returns the key and value for this entry of the map. */
+upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
+ upb_strtable_iter i;
+ upb_MessageValue ret;
+ i.t = &map->table;
+ i.index = iter;
+ _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+ return ret;
+}
+
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
+ upb_strtable_iter i;
+ upb_MessageValue ret;
+ i.t = &map->table;
+ i.index = iter;
+ _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+ return ret;
+}
+
+/* void upb_MapIterator_SetValue(upb_Map *map, size_t iter, upb_MessageValue
+ * value); */
diff --git a/contrib/libs/grpc/third_party/upb/upb/map.h b/contrib/libs/grpc/third_party/upb/upb/map.h
new file mode 100644
index 0000000000..8ee0ddd05e
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/map.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_MAP_H_
+#define UPB_MAP_H_
+
+#include "google/protobuf/descriptor.upb.h"
+#include "upb/message_value.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type);
+
+/* Returns the number of entries in the map. */
+size_t upb_Map_Size(const upb_Map* map);
+
+/* Stores a value for the given key into |*val| (or the zero value if the key is
+ * not present). Returns whether the key was present. The |val| pointer may be
+ * NULL, in which case the function tests whether the given key is present. */
+bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
+ upb_MessageValue* val);
+
+/* Removes all entries in the map. */
+void upb_Map_Clear(upb_Map* map);
+
+typedef enum {
+ // LINT.IfChange
+ kUpb_MapInsertStatus_Inserted = 0,
+ kUpb_MapInsertStatus_Replaced = 1,
+ kUpb_MapInsertStatus_OutOfMemory = 2,
+ // LINT.ThenChange(//depot/google3/third_party/upb/upb/msg_internal.h)
+} upb_MapInsertStatus;
+
+/* Sets the given key to the given value, returning whether the key was inserted
+ * or replaced. If the key was inserted, then any existing iterators will be
+ * invalidated. */
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue val, upb_Arena* arena);
+
+/* Sets the given key to the given value. Returns false if memory allocation
+ * failed. If the key is newly inserted, then any existing iterators will be
+ * invalidated. */
+UPB_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key,
+ upb_MessageValue val, upb_Arena* arena) {
+ return upb_Map_Insert(map, key, val, arena) !=
+ kUpb_MapInsertStatus_OutOfMemory;
+}
+
+/* Deletes this key from the table. Returns true if the key was present. */
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key);
+
+/* Map iteration:
+ *
+ * size_t iter = kUpb_Map_Begin;
+ * while (upb_MapIterator_Next(map, &iter)) {
+ * upb_MessageValue key = upb_MapIterator_Key(map, iter);
+ * upb_MessageValue val = upb_MapIterator_Value(map, iter);
+ *
+ * // If mutating is desired.
+ * upb_MapIterator_SetValue(map, iter, value2);
+ * }
+ */
+
+/* Advances to the next entry. Returns false if no more entries are present. */
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
+
+/* Returns true if the iterator still points to a valid entry, or false if the
+ * iterator is past the last element. It is an error to call this function with
+ * kUpb_Map_Begin (you must call next() at least once first). */
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
+
+/* Returns the key and value for this entry of the map. */
+upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
+
+/* Sets the value for this entry. The iterator must not be done, and the
+ * iterator must not have been initialized const. */
+void upb_MapIterator_SetValue(upb_Map* map, size_t iter,
+ upb_MessageValue value);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_MAP_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/message_value.h b/contrib/libs/grpc/third_party/upb/upb/message_value.h
new file mode 100644
index 0000000000..a08b90fc1e
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/message_value.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_MESSAGE_VALUE_H_
+#define UPB_MESSAGE_VALUE_H_
+
+#include "google/protobuf/descriptor.upb.h"
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Definitions commn to both upb_Array and upb_Map.
+
+typedef union {
+ bool bool_val;
+ float float_val;
+ double double_val;
+ int32_t int32_val;
+ int64_t int64_val;
+ uint32_t uint32_val;
+ uint64_t uint64_val;
+ const upb_Map* map_val;
+ const upb_Message* msg_val;
+ const upb_Array* array_val;
+ upb_StringView str_val;
+} upb_MessageValue;
+
+typedef union {
+ upb_Map* map;
+ upb_Message* msg;
+ upb_Array* array;
+} upb_MutableMessageValue;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_MESSAGE_VALUE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/mini_table.c b/contrib/libs/grpc/third_party/upb/upb/mini_table.c
new file mode 100644
index 0000000000..cd53059738
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/mini_table.c
@@ -0,0 +1,1147 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/mini_table.h"
+
+#include <inttypes.h>
+#include <setjmp.h>
+
+#include "upb/msg_internal.h"
+#include "upb/upb.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+typedef enum {
+ kUpb_EncodedType_Double = 0,
+ kUpb_EncodedType_Float = 1,
+ kUpb_EncodedType_Fixed32 = 2,
+ kUpb_EncodedType_Fixed64 = 3,
+ kUpb_EncodedType_SFixed32 = 4,
+ kUpb_EncodedType_SFixed64 = 5,
+ kUpb_EncodedType_Int32 = 6,
+ kUpb_EncodedType_UInt32 = 7,
+ kUpb_EncodedType_SInt32 = 8,
+ kUpb_EncodedType_Int64 = 9,
+ kUpb_EncodedType_UInt64 = 10,
+ kUpb_EncodedType_SInt64 = 11,
+ kUpb_EncodedType_Enum = 12,
+ kUpb_EncodedType_Bool = 13,
+ kUpb_EncodedType_Bytes = 14,
+ kUpb_EncodedType_String = 15,
+ kUpb_EncodedType_Group = 16,
+ kUpb_EncodedType_Message = 17,
+
+ kUpb_EncodedType_RepeatedBase = 20,
+} upb_EncodedType;
+
+typedef enum {
+ kUpb_EncodedFieldModifier_FlipPacked = 1 << 0,
+ kUpb_EncodedFieldModifier_IsClosedEnum = 1 << 1,
+ // upb only.
+ kUpb_EncodedFieldModifier_IsProto3Singular = 1 << 2,
+ kUpb_EncodedFieldModifier_IsRequired = 1 << 3,
+} upb_EncodedFieldModifier;
+
+enum {
+ kUpb_EncodedValue_MinField = ' ',
+ kUpb_EncodedValue_MaxField = 'K',
+ kUpb_EncodedValue_MinModifier = 'L',
+ kUpb_EncodedValue_MaxModifier = '[',
+ kUpb_EncodedValue_End = '^',
+ kUpb_EncodedValue_MinSkip = '_',
+ kUpb_EncodedValue_MaxSkip = '~',
+ kUpb_EncodedValue_OneofSeparator = '~',
+ kUpb_EncodedValue_FieldSeparator = '|',
+ kUpb_EncodedValue_MinOneofField = ' ',
+ kUpb_EncodedValue_MaxOneofField = 'b',
+ kUpb_EncodedValue_MaxEnumMask = 'A',
+};
+
+char upb_ToBase92(int8_t ch) {
+ static const char kUpb_ToBase92[] = {
+ ' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
+ '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+ 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+ 'Z', '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '{', '|', '}', '~',
+ };
+
+ UPB_ASSERT(0 <= ch && ch < 92);
+ return kUpb_ToBase92[ch];
+}
+
+char upb_FromBase92(uint8_t ch) {
+ static const int8_t kUpb_FromBase92[] = {
+ 0, 1, -1, 2, 3, 4, 5, -1, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ };
+
+ if (' ' > ch || ch > '~') return -1;
+ return kUpb_FromBase92[ch - ' '];
+}
+
+bool upb_IsTypePackable(upb_FieldType type) {
+ // clang-format off
+ static const unsigned kUnpackableTypes =
+ (1 << kUpb_FieldType_String) |
+ (1 << kUpb_FieldType_Bytes) |
+ (1 << kUpb_FieldType_Message) |
+ (1 << kUpb_FieldType_Group);
+ // clang-format on
+ return (1 << type) & ~kUnpackableTypes;
+}
+
+/** upb_MtDataEncoder *********************************************************/
+
+typedef struct {
+ uint64_t present_values_mask;
+ uint32_t last_written_value;
+} upb_MtDataEncoderInternal_EnumState;
+
+typedef struct {
+ uint64_t msg_modifiers;
+ uint32_t last_field_num;
+ enum {
+ kUpb_OneofState_NotStarted,
+ kUpb_OneofState_StartedOneof,
+ kUpb_OneofState_EmittedOneofField,
+ } oneof_state;
+} upb_MtDataEncoderInternal_MsgState;
+
+typedef struct {
+ char* buf_start; // Only for checking kUpb_MtDataEncoder_MinSize.
+ union {
+ upb_MtDataEncoderInternal_EnumState enum_state;
+ upb_MtDataEncoderInternal_MsgState msg_state;
+ } state;
+} upb_MtDataEncoderInternal;
+
+static upb_MtDataEncoderInternal* upb_MtDataEncoder_GetInternal(
+ upb_MtDataEncoder* e, char* buf_start) {
+ UPB_ASSERT(sizeof(upb_MtDataEncoderInternal) <= sizeof(e->internal));
+ upb_MtDataEncoderInternal* ret = (upb_MtDataEncoderInternal*)e->internal;
+ ret->buf_start = buf_start;
+ return ret;
+}
+
+static char* upb_MtDataEncoder_Put(upb_MtDataEncoder* e, char* ptr, char ch) {
+ upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+ UPB_ASSERT(ptr - in->buf_start < kUpb_MtDataEncoder_MinSize);
+ if (ptr == e->end) return NULL;
+ *ptr++ = upb_ToBase92(ch);
+ return ptr;
+}
+
+static char* upb_MtDataEncoder_PutBase92Varint(upb_MtDataEncoder* e, char* ptr,
+ uint32_t val, int min, int max) {
+ int shift = _upb_Log2Ceiling(upb_FromBase92(max) - upb_FromBase92(min) + 1);
+ UPB_ASSERT(shift <= 6);
+ uint32_t mask = (1 << shift) - 1;
+ do {
+ uint32_t bits = val & mask;
+ ptr = upb_MtDataEncoder_Put(e, ptr, bits + upb_FromBase92(min));
+ if (!ptr) return NULL;
+ val >>= shift;
+ } while (val);
+ return ptr;
+}
+
+char* upb_MtDataEncoder_PutModifier(upb_MtDataEncoder* e, char* ptr,
+ uint64_t mod) {
+ if (mod) {
+ ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, mod,
+ kUpb_EncodedValue_MinModifier,
+ kUpb_EncodedValue_MaxModifier);
+ }
+ return ptr;
+}
+
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+ uint64_t msg_mod) {
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ in->state.msg_state.msg_modifiers = msg_mod;
+ in->state.msg_state.last_field_num = 0;
+ in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+ return upb_MtDataEncoder_PutModifier(e, ptr, msg_mod);
+}
+
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+ upb_FieldType type, uint32_t field_num,
+ uint64_t field_mod) {
+ static const char kUpb_TypeToEncoded[] = {
+ [kUpb_FieldType_Double] = kUpb_EncodedType_Double,
+ [kUpb_FieldType_Float] = kUpb_EncodedType_Float,
+ [kUpb_FieldType_Int64] = kUpb_EncodedType_Int64,
+ [kUpb_FieldType_UInt64] = kUpb_EncodedType_UInt64,
+ [kUpb_FieldType_Int32] = kUpb_EncodedType_Int32,
+ [kUpb_FieldType_Fixed64] = kUpb_EncodedType_Fixed64,
+ [kUpb_FieldType_Fixed32] = kUpb_EncodedType_Fixed32,
+ [kUpb_FieldType_Bool] = kUpb_EncodedType_Bool,
+ [kUpb_FieldType_String] = kUpb_EncodedType_String,
+ [kUpb_FieldType_Group] = kUpb_EncodedType_Group,
+ [kUpb_FieldType_Message] = kUpb_EncodedType_Message,
+ [kUpb_FieldType_Bytes] = kUpb_EncodedType_Bytes,
+ [kUpb_FieldType_UInt32] = kUpb_EncodedType_UInt32,
+ [kUpb_FieldType_Enum] = kUpb_EncodedType_Enum,
+ [kUpb_FieldType_SFixed32] = kUpb_EncodedType_SFixed32,
+ [kUpb_FieldType_SFixed64] = kUpb_EncodedType_SFixed64,
+ [kUpb_FieldType_SInt32] = kUpb_EncodedType_SInt32,
+ [kUpb_FieldType_SInt64] = kUpb_EncodedType_SInt64,
+ };
+
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ if (field_num <= in->state.msg_state.last_field_num) return NULL;
+ if (in->state.msg_state.last_field_num + 1 != field_num) {
+ // Put skip.
+ UPB_ASSERT(field_num > in->state.msg_state.last_field_num);
+ uint32_t skip = field_num - in->state.msg_state.last_field_num;
+ ptr = upb_MtDataEncoder_PutBase92Varint(
+ e, ptr, skip, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+ if (!ptr) return NULL;
+ }
+ in->state.msg_state.last_field_num = field_num;
+
+ uint32_t encoded_modifiers = 0;
+
+ // Put field type.
+ if (type == kUpb_FieldType_Enum &&
+ !(field_mod & kUpb_FieldModifier_IsClosedEnum)) {
+ type = kUpb_FieldType_Int32;
+ }
+
+ int encoded_type = kUpb_TypeToEncoded[type];
+ if (field_mod & kUpb_FieldModifier_IsRepeated) {
+ // Repeated fields shift the type number up (unlike other modifiers which
+ // are bit flags).
+ encoded_type += kUpb_EncodedType_RepeatedBase;
+
+ if (upb_IsTypePackable(type)) {
+ bool field_is_packed = field_mod & kUpb_FieldModifier_IsPacked;
+ bool default_is_packed = in->state.msg_state.msg_modifiers &
+ kUpb_MessageModifier_DefaultIsPacked;
+ if (field_is_packed != default_is_packed) {
+ encoded_modifiers |= kUpb_EncodedFieldModifier_FlipPacked;
+ }
+ }
+ }
+ ptr = upb_MtDataEncoder_Put(e, ptr, encoded_type);
+ if (!ptr) return NULL;
+
+ if (field_mod & kUpb_FieldModifier_IsProto3Singular) {
+ encoded_modifiers |= kUpb_EncodedFieldModifier_IsProto3Singular;
+ }
+ if (field_mod & kUpb_FieldModifier_IsRequired) {
+ encoded_modifiers |= kUpb_EncodedFieldModifier_IsRequired;
+ }
+ return upb_MtDataEncoder_PutModifier(e, ptr, encoded_modifiers);
+}
+
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr) {
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ if (in->state.msg_state.oneof_state == kUpb_OneofState_NotStarted) {
+ ptr = upb_MtDataEncoder_Put(e, ptr, upb_FromBase92(kUpb_EncodedValue_End));
+ } else {
+ ptr = upb_MtDataEncoder_Put(
+ e, ptr, upb_FromBase92(kUpb_EncodedValue_OneofSeparator));
+ }
+ in->state.msg_state.oneof_state = kUpb_OneofState_StartedOneof;
+ return ptr;
+}
+
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+ uint32_t field_num) {
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ if (in->state.msg_state.oneof_state == kUpb_OneofState_EmittedOneofField) {
+ ptr = upb_MtDataEncoder_Put(
+ e, ptr, upb_FromBase92(kUpb_EncodedValue_FieldSeparator));
+ if (!ptr) return NULL;
+ }
+ ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, field_num, upb_ToBase92(0),
+ upb_ToBase92(63));
+ in->state.msg_state.oneof_state = kUpb_OneofState_EmittedOneofField;
+ return ptr;
+}
+
+void upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e) {
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, NULL);
+ in->state.enum_state.present_values_mask = 0;
+ in->state.enum_state.last_written_value = 0;
+}
+
+static char* upb_MtDataEncoder_FlushDenseEnumMask(upb_MtDataEncoder* e,
+ char* ptr) {
+ upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+ ptr = upb_MtDataEncoder_Put(e, ptr, in->state.enum_state.present_values_mask);
+ in->state.enum_state.present_values_mask = 0;
+ in->state.enum_state.last_written_value += 5;
+ return ptr;
+}
+
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+ uint32_t val) {
+ // TODO(b/229641772): optimize this encoding.
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ UPB_ASSERT(val >= in->state.enum_state.last_written_value);
+ uint32_t delta = val - in->state.enum_state.last_written_value;
+ if (delta >= 5 && in->state.enum_state.present_values_mask) {
+ ptr = upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+ if (!ptr) {
+ return NULL;
+ }
+ delta -= 5;
+ }
+
+ if (delta >= 5) {
+ ptr = upb_MtDataEncoder_PutBase92Varint(
+ e, ptr, delta, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+ in->state.enum_state.last_written_value += delta;
+ delta = 0;
+ }
+
+ UPB_ASSERT((in->state.enum_state.present_values_mask >> delta) == 0);
+ in->state.enum_state.present_values_mask |= 1ULL << delta;
+ return ptr;
+}
+
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) {
+ upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+ if (!in->state.enum_state.present_values_mask) return ptr;
+ return upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+}
+
+const upb_MiniTable_Field* upb_MiniTable_FindFieldByNumber(
+ const upb_MiniTable* table, uint32_t number) {
+ int n = table->field_count;
+ for (int i = 0; i < n; i++) {
+ if (table->fields[i].number == number) {
+ return &table->fields[i];
+ }
+ }
+ return NULL;
+}
+
+/** Data decoder **************************************************************/
+
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+ kUpb_LayoutItemType_OneofCase, // Oneof case.
+ kUpb_LayoutItemType_OneofField, // Oneof field data.
+ kUpb_LayoutItemType_Field, // Non-oneof field data.
+
+ kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field,
+} upb_LayoutItemType;
+
+#define kUpb_LayoutItem_IndexSentinel ((uint16_t)-1)
+
+typedef struct {
+ // Index of the corresponding field. When this is a oneof field, the field's
+ // offset will be the index of the next field in a linked list.
+ uint16_t field_index;
+ uint16_t offset;
+ upb_FieldRep rep;
+ upb_LayoutItemType type;
+} upb_LayoutItem;
+
+typedef struct {
+ upb_LayoutItem* data;
+ size_t size;
+ size_t capacity;
+} upb_LayoutItemVector;
+
+typedef struct {
+ const char* end;
+ upb_MiniTable* table;
+ upb_MiniTable_Field* fields;
+ upb_MiniTablePlatform platform;
+ upb_LayoutItemVector vec;
+ upb_Arena* arena;
+ upb_Status* status;
+ jmp_buf err;
+} upb_MtDecoder;
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void upb_MtDecoder_ErrorFormat(upb_MtDecoder* d,
+ const char* fmt, ...) {
+ va_list argp;
+ upb_Status_SetErrorMessage(d->status, "Error building mini table: ");
+ va_start(argp, fmt);
+ upb_Status_VAppendErrorFormat(d->status, fmt, argp);
+ va_end(argp);
+ UPB_LONGJMP(d->err, 1);
+}
+
+static void upb_MtDecoder_CheckOutOfMemory(upb_MtDecoder* d, const void* ptr) {
+ if (!ptr) upb_MtDecoder_ErrorFormat(d, "Out of memory");
+}
+
+// In each field's offset, we temporarily store a presence classifier:
+enum PresenceClass {
+ kNoPresence = 0,
+ kHasbitPresence = 1,
+ kRequiredPresence = 2,
+ kOneofBase = 3,
+ // Negative values refer to a specific oneof with that number. Positive
+ // values >= kOneofBase indicate that this field is in a oneof, and specify
+ // the next field in this oneof's linked list.
+};
+
+static const char* upb_MiniTable_DecodeBase92Varint(upb_MtDecoder* d,
+ const char* ptr,
+ char first_ch, uint8_t min,
+ uint8_t max,
+ uint32_t* out_val) {
+ uint32_t val = 0;
+ uint32_t shift = 0;
+ const int bits_per_char =
+ _upb_Log2Ceiling(upb_FromBase92(max) - upb_FromBase92(min));
+ char ch = first_ch;
+ while (1) {
+ uint32_t bits = upb_FromBase92(ch) - upb_FromBase92(min);
+ UPB_ASSERT(shift < 32);
+ val |= bits << shift;
+ if (ptr == d->end || *ptr < min || max < *ptr) {
+ *out_val = val;
+ return ptr;
+ }
+ ch = *ptr++;
+ shift += bits_per_char;
+ }
+}
+
+static bool upb_MiniTable_HasSub(upb_MiniTable_Field* field,
+ uint64_t msg_modifiers) {
+ switch (field->descriptortype) {
+ case kUpb_FieldType_Message:
+ case kUpb_FieldType_Group:
+ case kUpb_FieldType_Enum:
+ return true;
+ case kUpb_FieldType_String:
+ if (!(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) {
+ field->descriptortype = kUpb_FieldType_Bytes;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+static bool upb_MtDecoder_FieldIsPackable(upb_MiniTable_Field* field) {
+ return (field->mode & kUpb_FieldMode_Array) &&
+ upb_IsTypePackable(field->descriptortype);
+}
+
+static void upb_MiniTable_SetTypeAndSub(upb_MiniTable_Field* field,
+ upb_FieldType type, uint32_t* sub_count,
+ uint64_t msg_modifiers) {
+ field->descriptortype = type;
+ if (upb_MiniTable_HasSub(field, msg_modifiers)) {
+ field->submsg_index = sub_count ? (*sub_count)++ : 0;
+ } else {
+ field->submsg_index = kUpb_NoSub;
+ }
+
+ if (upb_MtDecoder_FieldIsPackable(field) &&
+ (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) {
+ field->mode |= kUpb_LabelFlags_IsPacked;
+ }
+}
+
+static void upb_MiniTable_SetField(upb_MtDecoder* d, uint8_t ch,
+ upb_MiniTable_Field* field,
+ uint64_t msg_modifiers,
+ uint32_t* sub_count) {
+ static const char kUpb_EncodedToFieldRep[] = {
+ [kUpb_EncodedType_Double] = kUpb_FieldRep_8Byte,
+ [kUpb_EncodedType_Float] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_Int64] = kUpb_FieldRep_8Byte,
+ [kUpb_EncodedType_UInt64] = kUpb_FieldRep_8Byte,
+ [kUpb_EncodedType_Int32] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_Fixed64] = kUpb_FieldRep_8Byte,
+ [kUpb_EncodedType_Fixed32] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_Bool] = kUpb_FieldRep_1Byte,
+ [kUpb_EncodedType_String] = kUpb_FieldRep_StringView,
+ [kUpb_EncodedType_Group] = kUpb_FieldRep_Pointer,
+ [kUpb_EncodedType_Message] = kUpb_FieldRep_Pointer,
+ [kUpb_EncodedType_Bytes] = kUpb_FieldRep_StringView,
+ [kUpb_EncodedType_UInt32] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_Enum] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_SFixed32] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_SFixed64] = kUpb_FieldRep_8Byte,
+ [kUpb_EncodedType_SInt32] = kUpb_FieldRep_4Byte,
+ [kUpb_EncodedType_SInt64] = kUpb_FieldRep_8Byte,
+ };
+
+ static const char kUpb_EncodedToType[] = {
+ [kUpb_EncodedType_Double] = kUpb_FieldType_Double,
+ [kUpb_EncodedType_Float] = kUpb_FieldType_Float,
+ [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64,
+ [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64,
+ [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32,
+ [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64,
+ [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32,
+ [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool,
+ [kUpb_EncodedType_String] = kUpb_FieldType_String,
+ [kUpb_EncodedType_Group] = kUpb_FieldType_Group,
+ [kUpb_EncodedType_Message] = kUpb_FieldType_Message,
+ [kUpb_EncodedType_Bytes] = kUpb_FieldType_Bytes,
+ [kUpb_EncodedType_UInt32] = kUpb_FieldType_UInt32,
+ [kUpb_EncodedType_Enum] = kUpb_FieldType_Enum,
+ [kUpb_EncodedType_SFixed32] = kUpb_FieldType_SFixed32,
+ [kUpb_EncodedType_SFixed64] = kUpb_FieldType_SFixed64,
+ [kUpb_EncodedType_SInt32] = kUpb_FieldType_SInt32,
+ [kUpb_EncodedType_SInt64] = kUpb_FieldType_SInt64,
+ };
+
+ int8_t type = upb_FromBase92(ch);
+ if (ch >= upb_ToBase92(kUpb_EncodedType_RepeatedBase)) {
+ type -= kUpb_EncodedType_RepeatedBase;
+ field->mode = kUpb_FieldMode_Array;
+ field->mode |= kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift;
+ field->offset = kNoPresence;
+ } else {
+ field->mode = kUpb_FieldMode_Scalar;
+ field->mode |= kUpb_EncodedToFieldRep[type] << kUpb_FieldRep_Shift;
+ field->offset = kHasbitPresence;
+ }
+ if (type >= 18) {
+ upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
+ UPB_UNREACHABLE();
+ }
+ upb_MiniTable_SetTypeAndSub(field, kUpb_EncodedToType[type], sub_count,
+ msg_modifiers);
+}
+
+static void upb_MtDecoder_ModifyField(upb_MtDecoder* d,
+ uint32_t message_modifiers,
+ uint32_t field_modifiers,
+ upb_MiniTable_Field* field) {
+ if (field_modifiers & kUpb_EncodedFieldModifier_FlipPacked) {
+ if (!upb_MtDecoder_FieldIsPackable(field)) {
+ upb_MtDecoder_ErrorFormat(
+ d, "Cannot flip packed on unpackable field %" PRIu32, field->number);
+ UPB_UNREACHABLE();
+ }
+ field->mode ^= kUpb_LabelFlags_IsPacked;
+ }
+
+ bool singular = field_modifiers & kUpb_EncodedFieldModifier_IsProto3Singular;
+ bool required = field_modifiers & kUpb_EncodedFieldModifier_IsRequired;
+
+ // Validate.
+ if ((singular || required) && field->offset != kHasbitPresence) {
+ upb_MtDecoder_ErrorFormat(
+ d, "Invalid modifier(s) for repeated field %" PRIu32, field->number);
+ UPB_UNREACHABLE();
+ }
+ if (singular && required) {
+ upb_MtDecoder_ErrorFormat(
+ d, "Field %" PRIu32 " cannot be both singular and required",
+ field->number);
+ UPB_UNREACHABLE();
+ }
+
+ if (singular) field->offset = kNoPresence;
+ if (required) {
+ field->offset = kRequiredPresence;
+ }
+}
+
+static void upb_MtDecoder_PushItem(upb_MtDecoder* d, upb_LayoutItem item) {
+ if (d->vec.size == d->vec.capacity) {
+ size_t new_cap = UPB_MAX(8, d->vec.size * 2);
+ d->vec.data = realloc(d->vec.data, new_cap * sizeof(*d->vec.data));
+ upb_MtDecoder_CheckOutOfMemory(d, d->vec.data);
+ d->vec.capacity = new_cap;
+ }
+ d->vec.data[d->vec.size++] = item;
+}
+
+static void upb_MtDecoder_PushOneof(upb_MtDecoder* d, upb_LayoutItem item) {
+ if (item.field_index == kUpb_LayoutItem_IndexSentinel) {
+ upb_MtDecoder_ErrorFormat(d, "Empty oneof");
+ UPB_UNREACHABLE();
+ }
+ item.field_index -= kOneofBase;
+
+ // Push oneof data.
+ item.type = kUpb_LayoutItemType_OneofField;
+ upb_MtDecoder_PushItem(d, item);
+
+ // Push oneof case.
+ item.rep = kUpb_FieldRep_4Byte; // Field Number.
+ item.type = kUpb_LayoutItemType_OneofCase;
+ upb_MtDecoder_PushItem(d, item);
+}
+
+size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
+ upb_MiniTablePlatform platform) {
+ static const uint8_t kRepToSize32[] = {
+ [kUpb_FieldRep_1Byte] = 1, [kUpb_FieldRep_4Byte] = 4,
+ [kUpb_FieldRep_Pointer] = 4, [kUpb_FieldRep_StringView] = 8,
+ [kUpb_FieldRep_8Byte] = 8,
+ };
+ static const uint8_t kRepToSize64[] = {
+ [kUpb_FieldRep_1Byte] = 1, [kUpb_FieldRep_4Byte] = 4,
+ [kUpb_FieldRep_Pointer] = 8, [kUpb_FieldRep_StringView] = 16,
+ [kUpb_FieldRep_8Byte] = 8,
+ };
+ UPB_ASSERT(sizeof(upb_StringView) ==
+ UPB_SIZE(kRepToSize32, kRepToSize64)[kUpb_FieldRep_StringView]);
+ return platform == kUpb_MiniTablePlatform_32Bit ? kRepToSize32[rep]
+ : kRepToSize64[rep];
+}
+
+size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
+ upb_MiniTablePlatform platform) {
+ static const uint8_t kRepToAlign32[] = {
+ [kUpb_FieldRep_1Byte] = 1, [kUpb_FieldRep_4Byte] = 4,
+ [kUpb_FieldRep_Pointer] = 4, [kUpb_FieldRep_StringView] = 4,
+ [kUpb_FieldRep_8Byte] = 8,
+ };
+ static const uint8_t kRepToAlign64[] = {
+ [kUpb_FieldRep_1Byte] = 1, [kUpb_FieldRep_4Byte] = 4,
+ [kUpb_FieldRep_Pointer] = 8, [kUpb_FieldRep_StringView] = 8,
+ [kUpb_FieldRep_8Byte] = 8,
+ };
+ UPB_ASSERT(UPB_ALIGN_OF(upb_StringView) ==
+ UPB_SIZE(kRepToAlign32, kRepToAlign64)[kUpb_FieldRep_StringView]);
+ return platform == kUpb_MiniTablePlatform_32Bit ? kRepToAlign32[rep]
+ : kRepToAlign64[rep];
+}
+
+static const char* upb_MtDecoder_DecodeOneofField(upb_MtDecoder* d,
+ const char* ptr,
+ char first_ch,
+ upb_LayoutItem* item) {
+ uint32_t field_num;
+ ptr = upb_MiniTable_DecodeBase92Varint(
+ d, ptr, first_ch, kUpb_EncodedValue_MinOneofField,
+ kUpb_EncodedValue_MaxOneofField, &field_num);
+ upb_MiniTable_Field* f =
+ (void*)upb_MiniTable_FindFieldByNumber(d->table, field_num);
+
+ if (!f) {
+ upb_MtDecoder_ErrorFormat(d,
+ "Couldn't add field number %" PRIu32
+ " to oneof, no such field number.",
+ field_num);
+ UPB_UNREACHABLE();
+ }
+ if (f->offset != kHasbitPresence) {
+ upb_MtDecoder_ErrorFormat(
+ d,
+ "Cannot add repeated, required, or singular field %" PRIu32
+ " to oneof.",
+ field_num);
+ UPB_UNREACHABLE();
+ }
+
+ // Oneof storage must be large enough to accommodate the largest member.
+ int rep = f->mode >> kUpb_FieldRep_Shift;
+ if (upb_MtDecoder_SizeOfRep(rep, d->platform) >
+ upb_MtDecoder_SizeOfRep(item->rep, d->platform)) {
+ item->rep = rep;
+ }
+ // Prepend this field to the linked list.
+ f->offset = item->field_index;
+ item->field_index = (f - d->fields) + kOneofBase;
+ return ptr;
+}
+
+static const char* upb_MtDecoder_DecodeOneofs(upb_MtDecoder* d,
+ const char* ptr) {
+ upb_LayoutItem item = {.rep = 0,
+ .field_index = kUpb_LayoutItem_IndexSentinel};
+ while (ptr < d->end) {
+ char ch = *ptr++;
+ if (ch == kUpb_EncodedValue_FieldSeparator) {
+ // Field separator, no action needed.
+ } else if (ch == kUpb_EncodedValue_OneofSeparator) {
+ // End of oneof.
+ upb_MtDecoder_PushOneof(d, item);
+ item.field_index = kUpb_LayoutItem_IndexSentinel; // Move to next oneof.
+ } else {
+ ptr = upb_MtDecoder_DecodeOneofField(d, ptr, ch, &item);
+ }
+ }
+
+ // Push final oneof.
+ upb_MtDecoder_PushOneof(d, item);
+ return ptr;
+}
+
+static const char* upb_MtDecoder_ParseModifier(upb_MtDecoder* d,
+ const char* ptr, char first_ch,
+ upb_MiniTable_Field* last_field,
+ uint64_t* msg_modifiers) {
+ uint32_t mod;
+ ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, first_ch,
+ kUpb_EncodedValue_MinModifier,
+ kUpb_EncodedValue_MaxModifier, &mod);
+ if (last_field) {
+ upb_MtDecoder_ModifyField(d, *msg_modifiers, mod, last_field);
+ } else {
+ if (!d->table) {
+ upb_MtDecoder_ErrorFormat(d, "Extensions cannot have message modifiers");
+ UPB_UNREACHABLE();
+ }
+ *msg_modifiers = mod;
+ }
+
+ return ptr;
+}
+
+static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, uint32_t sub_count) {
+ size_t subs_bytes = sizeof(*d->table->subs) * sub_count;
+ d->table->subs = upb_Arena_Malloc(d->arena, subs_bytes);
+ upb_MtDecoder_CheckOutOfMemory(d, d->table->subs);
+}
+
+static void upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr, size_t len,
+ void* fields, size_t field_size,
+ uint16_t* field_count, uint32_t* sub_count) {
+ uint64_t msg_modifiers = 0;
+ uint32_t last_field_number = 0;
+ upb_MiniTable_Field* last_field = NULL;
+ bool need_dense_below = d->table != NULL;
+
+ d->end = UPB_PTRADD(ptr, len);
+
+ while (ptr < d->end) {
+ char ch = *ptr++;
+ if (ch <= kUpb_EncodedValue_MaxField) {
+ upb_MiniTable_Field* field = fields;
+ *field_count += 1;
+ fields = (char*)fields + field_size;
+ field->number = ++last_field_number;
+ last_field = field;
+ upb_MiniTable_SetField(d, ch, field, msg_modifiers, sub_count);
+ } else if (kUpb_EncodedValue_MinModifier <= ch &&
+ ch <= kUpb_EncodedValue_MaxModifier) {
+ ptr = upb_MtDecoder_ParseModifier(d, ptr, ch, last_field, &msg_modifiers);
+ if (msg_modifiers & kUpb_MessageModifier_IsExtendable) {
+ d->table->ext |= kUpb_ExtMode_Extendable;
+ }
+ } else if (ch == kUpb_EncodedValue_End) {
+ if (!d->table) {
+ upb_MtDecoder_ErrorFormat(d, "Extensions cannot have oneofs.");
+ UPB_UNREACHABLE();
+ }
+ ptr = upb_MtDecoder_DecodeOneofs(d, ptr);
+ } else if (kUpb_EncodedValue_MinSkip <= ch &&
+ ch <= kUpb_EncodedValue_MaxSkip) {
+ if (need_dense_below) {
+ d->table->dense_below = d->table->field_count;
+ need_dense_below = false;
+ }
+ uint32_t skip;
+ ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, ch,
+ kUpb_EncodedValue_MinSkip,
+ kUpb_EncodedValue_MaxSkip, &skip);
+ last_field_number += skip;
+ last_field_number--; // Next field seen will increment.
+ }
+ }
+
+ if (need_dense_below) {
+ d->table->dense_below = d->table->field_count;
+ }
+}
+
+static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
+ size_t len) {
+ // Buffer length is an upper bound on the number of fields. We will return
+ // what we don't use.
+ d->fields = upb_Arena_Malloc(d->arena, sizeof(*d->fields) * len);
+ upb_MtDecoder_CheckOutOfMemory(d, d->fields);
+
+ uint32_t sub_count = 0;
+ d->table->field_count = 0;
+ d->table->fields = d->fields;
+ upb_MtDecoder_Parse(d, data, len, d->fields, sizeof(*d->fields),
+ &d->table->field_count, &sub_count);
+
+ upb_Arena_ShrinkLast(d->arena, d->fields, sizeof(*d->fields) * len,
+ sizeof(*d->fields) * d->table->field_count);
+ d->table->fields = d->fields;
+ upb_MtDecoder_AllocateSubs(d, sub_count);
+}
+
+int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
+ const upb_LayoutItem* a = _a;
+ const upb_LayoutItem* b = _b;
+ // Currently we just sort by:
+ // 1. rep (smallest fields first)
+ // 2. type (oneof cases first)
+ // 2. field_index (smallest numbers first)
+ // The main goal of this is to reduce space lost to padding.
+ // Later we may have more subtle reasons to prefer a different ordering.
+ const int rep_bits = _upb_Log2Ceiling(kUpb_FieldRep_Max);
+ const int type_bits = _upb_Log2Ceiling(kUpb_LayoutItemType_Max);
+ const int idx_bits = (sizeof(a->field_index) * 8);
+ UPB_ASSERT(idx_bits + rep_bits + type_bits < 32);
+#define UPB_COMBINE(rep, ty, idx) (((rep << type_bits) | ty) << idx_bits) | idx
+ uint32_t a_packed = UPB_COMBINE(a->rep, a->type, a->field_index);
+ uint32_t b_packed = UPB_COMBINE(b->rep, b->type, b->field_index);
+ assert(a_packed != b_packed);
+#undef UPB_COMBINE
+ return a_packed < b_packed ? -1 : 1;
+}
+
+static bool upb_MtDecoder_SortLayoutItems(upb_MtDecoder* d) {
+ // Add items for all non-oneof fields (oneofs were already added).
+ int n = d->table->field_count;
+ for (int i = 0; i < n; i++) {
+ upb_MiniTable_Field* f = &d->fields[i];
+ if (f->offset >= kOneofBase) continue;
+ upb_LayoutItem item = {.field_index = i,
+ .rep = f->mode >> kUpb_FieldRep_Shift,
+ .type = kUpb_LayoutItemType_Field};
+ upb_MtDecoder_PushItem(d, item);
+ }
+
+ if (d->vec.size) {
+ qsort(d->vec.data, d->vec.size, sizeof(*d->vec.data),
+ upb_MtDecoder_CompareFields);
+ }
+
+ return true;
+}
+
+static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) {
+ return (n + d - 1) / d;
+}
+
+static void upb_MtDecoder_AssignHasbits(upb_MiniTable* ret) {
+ int n = ret->field_count;
+ int last_hasbit = 0; // 0 cannot be used.
+
+ // First assign required fields, which must have the lowest hasbits.
+ for (int i = 0; i < n; i++) {
+ upb_MiniTable_Field* field = (upb_MiniTable_Field*)&ret->fields[i];
+ if (field->offset == kRequiredPresence) {
+ field->presence = ++last_hasbit;
+ } else if (field->offset == kNoPresence) {
+ field->presence = 0;
+ }
+ }
+ ret->required_count = last_hasbit;
+
+ // Next assign non-required hasbit fields.
+ for (int i = 0; i < n; i++) {
+ upb_MiniTable_Field* field = (upb_MiniTable_Field*)&ret->fields[i];
+ if (field->offset == kHasbitPresence) {
+ field->presence = ++last_hasbit;
+ }
+ }
+
+ ret->size = last_hasbit ? upb_MiniTable_DivideRoundUp(last_hasbit + 1, 8) : 0;
+}
+
+size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
+ size_t size = upb_MtDecoder_SizeOfRep(rep, d->platform);
+ size_t align = upb_MtDecoder_AlignOfRep(rep, d->platform);
+ size_t ret = UPB_ALIGN_UP(d->table->size, align);
+ d->table->size = ret + size;
+ return ret;
+}
+
+static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
+ upb_LayoutItem* end = UPB_PTRADD(d->vec.data, d->vec.size);
+
+ // Compute offsets.
+ for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+ item->offset = upb_MtDecoder_Place(d, item->rep);
+ }
+
+ // Assign oneof case offsets. We must do these first, since assigning
+ // actual offsets will overwrite the links of the linked list.
+ for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+ if (item->type != kUpb_LayoutItemType_OneofCase) continue;
+ upb_MiniTable_Field* f = &d->fields[item->field_index];
+ while (true) {
+ f->presence = ~item->offset;
+ if (f->offset == kUpb_LayoutItem_IndexSentinel) break;
+ UPB_ASSERT(f->offset - kOneofBase < d->table->field_count);
+ f = &d->fields[f->offset - kOneofBase];
+ }
+ }
+
+ // Assign offsets.
+ for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+ upb_MiniTable_Field* f = &d->fields[item->field_index];
+ switch (item->type) {
+ case kUpb_LayoutItemType_OneofField:
+ while (true) {
+ uint16_t next_offset = f->offset;
+ f->offset = item->offset;
+ if (next_offset == kUpb_LayoutItem_IndexSentinel) break;
+ f = &d->fields[next_offset - kOneofBase];
+ }
+ break;
+ case kUpb_LayoutItemType_Field:
+ f->offset = item->offset;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The fasttable parser (supported on 64-bit only) depends on this being a
+ // multiple of 8 in order to satisfy UPB_MALLOC_ALIGN, which is also 8.
+ //
+ // On 32-bit we could potentially make this smaller, but there is no
+ // compelling reason to optimize this right now.
+ d->table->size = UPB_ALIGN_UP(d->table->size, 8);
+}
+
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena, void** buf,
+ size_t* buf_size,
+ upb_Status* status) {
+ upb_MtDecoder decoder = {
+ .platform = platform,
+ .vec =
+ {
+ .data = *buf,
+ .capacity = *buf_size / sizeof(*decoder.vec.data),
+ .size = 0,
+ },
+ .arena = arena,
+ .status = status,
+ .table = upb_Arena_Malloc(arena, sizeof(*decoder.table)),
+ };
+
+ if (UPB_SETJMP(decoder.err)) {
+ decoder.table = NULL;
+ goto done;
+ }
+
+ upb_MtDecoder_CheckOutOfMemory(&decoder, decoder.table);
+
+ decoder.table->size = 0;
+ decoder.table->field_count = 0;
+ decoder.table->ext = kUpb_ExtMode_NonExtendable;
+ decoder.table->dense_below = 0;
+ decoder.table->table_mask = 0;
+ decoder.table->required_count = 0;
+
+ upb_MtDecoder_ParseMessage(&decoder, data, len);
+ upb_MtDecoder_AssignHasbits(decoder.table);
+ upb_MtDecoder_SortLayoutItems(&decoder);
+ upb_MtDecoder_AssignOffsets(&decoder);
+
+done:
+ *buf = decoder.vec.data;
+ *buf_size = decoder.vec.capacity / sizeof(*decoder.vec.data);
+ return decoder.table;
+}
+
+upb_MiniTable* upb_MiniTable_BuildMessageSet(upb_MiniTablePlatform platform,
+ upb_Arena* arena) {
+ upb_MiniTable* ret = upb_Arena_Malloc(arena, sizeof(*ret));
+ if (!ret) return NULL;
+
+ ret->size = 0;
+ ret->field_count = 0;
+ ret->ext = kUpb_ExtMode_IsMessageSet;
+ ret->dense_below = 0;
+ ret->table_mask = 0;
+ ret->required_count = 0;
+ return ret;
+}
+
+upb_MiniTable* upb_MiniTable_BuildMapEntry(upb_FieldType key_type,
+ upb_FieldType value_type,
+ bool value_is_proto3_enum,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena) {
+ upb_MiniTable* ret = upb_Arena_Malloc(arena, sizeof(*ret));
+ upb_MiniTable_Field* fields = upb_Arena_Malloc(arena, sizeof(*fields) * 2);
+ if (!ret || !fields) return NULL;
+
+ upb_MiniTable_Sub* subs = NULL;
+ if (value_is_proto3_enum) value_type = kUpb_FieldType_Int32;
+ if (value_type == kUpb_FieldType_Message ||
+ value_type == kUpb_FieldType_Group || value_type == kUpb_FieldType_Enum) {
+ subs = upb_Arena_Malloc(arena, sizeof(*subs));
+ if (!subs) return NULL;
+ }
+
+ size_t field_size =
+ upb_MtDecoder_SizeOfRep(kUpb_FieldRep_StringView, platform);
+
+ fields[0].number = 1;
+ fields[1].number = 2;
+ fields[0].mode = kUpb_FieldMode_Scalar;
+ fields[1].mode = kUpb_FieldMode_Scalar;
+ fields[0].presence = 0;
+ fields[1].presence = 0;
+ fields[0].offset = 0;
+ fields[1].offset = field_size;
+
+ upb_MiniTable_SetTypeAndSub(&fields[0], key_type, NULL, 0);
+ upb_MiniTable_SetTypeAndSub(&fields[1], value_type, NULL, 0);
+
+ ret->size = UPB_ALIGN_UP(2 * field_size, 8);
+ ret->field_count = 2;
+ ret->ext = kUpb_ExtMode_NonExtendable | kUpb_ExtMode_IsMapEntry;
+ ret->dense_below = 2;
+ ret->table_mask = 0;
+ ret->required_count = 0;
+ ret->subs = subs;
+ ret->fields = fields;
+ return ret;
+}
+
+static bool upb_MiniTable_BuildEnumValue(upb_MtDecoder* d,
+ upb_MiniTable_Enum* table,
+ uint32_t val, upb_Arena* arena) {
+ if (val < 64) {
+ table->mask |= 1ULL << val;
+ return true;
+ }
+
+ int32_t* values = (void*)table->values;
+ values = upb_Arena_Realloc(arena, values, table->value_count * 4,
+ (table->value_count + 1) * 4);
+ upb_MtDecoder_CheckOutOfMemory(d, values);
+ values[table->value_count++] = (int32_t)val;
+ table->values = values;
+ return true;
+}
+
+upb_MiniTable_Enum* upb_MiniTable_BuildEnum(const char* data, size_t len,
+ upb_Arena* arena,
+ upb_Status* status) {
+ upb_MtDecoder d = {
+ .status = status,
+ .end = UPB_PTRADD(data, len),
+ };
+
+ if (UPB_SETJMP(d.err)) {
+ return NULL;
+ }
+
+ upb_MiniTable_Enum* table = upb_Arena_Malloc(arena, sizeof(*table));
+ upb_MtDecoder_CheckOutOfMemory(&d, table);
+
+ table->mask = 0;
+ table->value_count = 0;
+ table->values = NULL;
+
+ const char* ptr = data;
+ uint32_t base = 0;
+
+ while (ptr < d.end) {
+ char ch = *ptr++;
+ if (ch <= kUpb_EncodedValue_MaxEnumMask) {
+ uint32_t mask = upb_FromBase92(ch);
+ for (int i = 0; i < 5; i++, base++, mask >>= 1) {
+ if (mask & 1) {
+ if (!upb_MiniTable_BuildEnumValue(&d, table, base, arena)) {
+ return NULL;
+ }
+ }
+ }
+ } else if (kUpb_EncodedValue_MinSkip <= ch &&
+ ch <= kUpb_EncodedValue_MaxSkip) {
+ uint32_t skip;
+ ptr = upb_MiniTable_DecodeBase92Varint(&d, ptr, ch,
+ kUpb_EncodedValue_MinSkip,
+ kUpb_EncodedValue_MaxSkip, &skip);
+ base += skip;
+ } else {
+ upb_Status_SetErrorFormat(status, "Unexpected character: %c", ch);
+ return NULL;
+ }
+ }
+
+ return table;
+}
+
+bool upb_MiniTable_BuildExtension(const char* data, size_t len,
+ upb_MiniTable_Extension* ext,
+ upb_MiniTable_Sub sub, upb_Status* status) {
+ upb_MtDecoder decoder = {
+ .arena = NULL,
+ .status = status,
+ .table = NULL,
+ };
+
+ if (UPB_SETJMP(decoder.err)) {
+ return false;
+ }
+
+ uint16_t count = 0;
+ upb_MtDecoder_Parse(&decoder, data, len, ext, sizeof(*ext), &count, NULL);
+ ext->field.mode |= kUpb_LabelFlags_IsExtension;
+ ext->field.offset = 0;
+ return true;
+}
+
+upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena, upb_Status* status) {
+ void* buf = NULL;
+ size_t size = 0;
+ upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(data, len, platform, arena,
+ &buf, &size, status);
+ free(buf);
+ return ret;
+}
+
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+ upb_MiniTable_Field* field,
+ const upb_MiniTable* sub) {
+ UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+ (uintptr_t)field <
+ (uintptr_t)(table->fields + table->field_count));
+ if (sub->ext & kUpb_ExtMode_IsMapEntry) {
+ field->mode =
+ (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift) | kUpb_FieldMode_Map;
+ }
+ upb_MiniTable_Sub* table_sub = (void*)&table->subs[field->submsg_index];
+ table_sub->submsg = sub;
+}
+
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTable_Field* field,
+ const upb_MiniTable_Enum* sub) {
+ UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+ (uintptr_t)field <
+ (uintptr_t)(table->fields + table->field_count));
+ upb_MiniTable_Sub* table_sub = (void*)&table->subs[field->submsg_index];
+ table_sub->subenum = sub;
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/mini_table.h b/contrib/libs/grpc/third_party/upb/upb/mini_table.h
new file mode 100644
index 0000000000..6c41f810eb
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/mini_table.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009-2022, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_MINI_TABLE_H_
+#define UPB_MINI_TABLE_H_
+
+#include "upb/msg_internal.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MiniTable_Field* upb_MiniTable_FindFieldByNumber(
+ const upb_MiniTable* table, uint32_t number);
+
+UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
+ const upb_MiniTable* mini_table, const upb_MiniTable_Field* field) {
+ return mini_table->subs[field->submsg_index].submsg;
+}
+
+UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e,
+ int32_t val) {
+ uint32_t uval = (uint32_t)val;
+ if (uval < 64) return e->mask & (1ULL << uval);
+ // OPT: binary search long lists?
+ int n = e->value_count;
+ for (int i = 0; i < n; i++) {
+ if (e->values[i] == val) return true;
+ }
+ return false;
+}
+
+/** upb_MtDataEncoder *********************************************************/
+
+// Functions to encode a string in a format that can be loaded by
+// upb_MiniTable_Build().
+
+typedef enum {
+ kUpb_MessageModifier_ValidateUtf8 = 1 << 0,
+ kUpb_MessageModifier_DefaultIsPacked = 1 << 1,
+ kUpb_MessageModifier_IsExtendable = 1 << 2,
+} kUpb_MessageModifier;
+
+typedef enum {
+ kUpb_FieldModifier_IsRepeated = 1 << 0,
+ kUpb_FieldModifier_IsPacked = 1 << 1,
+ kUpb_FieldModifier_IsClosedEnum = 1 << 2,
+ kUpb_FieldModifier_IsProto3Singular = 1 << 3,
+ kUpb_FieldModifier_IsRequired = 1 << 4,
+} kUpb_FieldModifier;
+
+typedef struct {
+ char* end; // Limit of the buffer passed as a parameter.
+ // Aliased to internal-only members in .cc.
+ char internal[32];
+} upb_MtDataEncoder;
+
+// If the input buffer has at least this many bytes available, the encoder call
+// is guaranteed to succeed (as long as field number order is maintained).
+#define kUpb_MtDataEncoder_MinSize 16
+
+// Encodes field/oneof information for a given message. The sequence of calls
+// should look like:
+//
+// upb_MtDataEncoder e;
+// char buf[256];
+// char* ptr = buf;
+// e.end = ptr + sizeof(buf);
+// ptr = upb_MtDataEncoder_StartMessage(&e, ptr);
+// // Fields *must* be in field number order.
+// ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+// ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+// ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//
+// // If oneofs are present. Oneofs must be encoded after regular fields.
+// ptr = upb_MiniTable_StartOneof(&e, ptr)
+// ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+// ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+// ptr = upb_MiniTable_StartOneof(&e, ptr);
+// ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+// ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+// Oneofs must be encoded after all regular fields.
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+ uint64_t msg_mod);
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+ upb_FieldType type, uint32_t field_num,
+ uint64_t field_mod);
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr);
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+ uint32_t field_num);
+
+// Encodes the set of values for a given enum. The values must be given in
+// order (after casting to uint32_t), and repeats are not allowed.
+void upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e);
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+ uint32_t val);
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr);
+
+/** upb_MiniTable *************************************************************/
+
+typedef enum {
+ kUpb_MiniTablePlatform_32Bit,
+ kUpb_MiniTablePlatform_64Bit,
+ kUpb_MiniTablePlatform_Native =
+ UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit),
+} upb_MiniTablePlatform;
+
+// Builds a mini table from the data encoded in the buffer [data, len]. If any
+// errors occur, returns NULL and sets a status message. In the success case,
+// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum
+// fields to link the table to the appropriate sub-tables.
+upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena, upb_Status* status);
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+ upb_MiniTable_Field* field,
+ const upb_MiniTable* sub);
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTable_Field* field,
+ const upb_MiniTable_Enum* sub);
+
+bool upb_MiniTable_BuildExtension(const char* data, size_t len,
+ upb_MiniTable_Extension* ext,
+ upb_MiniTable_Sub sub, upb_Status* status);
+
+// Special-case functions for MessageSet layout and map entries.
+upb_MiniTable* upb_MiniTable_BuildMessageSet(upb_MiniTablePlatform platform,
+ upb_Arena* arena);
+upb_MiniTable* upb_MiniTable_BuildMapEntry(upb_FieldType key_type,
+ upb_FieldType value_type,
+ bool value_is_proto3_enum,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena);
+
+upb_MiniTable_Enum* upb_MiniTable_BuildEnum(const char* data, size_t len,
+ upb_Arena* arena,
+ upb_Status* status);
+
+// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so
+// it can be reused from call to call, avoiding repeated realloc()/free().
+//
+// The caller owns `*buf` both before and after the call, and must free() it
+// when it is no longer in use. The function will realloc() `*buf` as
+// necessary, updating `*size` accordingly.
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+ upb_MiniTablePlatform platform,
+ upb_Arena* arena, void** buf,
+ size_t* buf_size, upb_Status* status);
+
+// For testing only.
+char upb_ToBase92(int8_t ch);
+char upb_FromBase92(uint8_t ch);
+bool upb_IsTypePackable(upb_FieldType type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_MINI_TABLE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/msg.c b/contrib/libs/grpc/third_party/upb/upb/msg.c
index 3734fc5491..036c62199d 100644
--- a/contrib/libs/grpc/third_party/upb/upb/msg.c
+++ b/contrib/libs/grpc/third_party/upb/upb/msg.c
@@ -27,12 +27,11 @@
#include "upb/msg.h"
+#include "upb/internal/table.h"
#include "upb/msg_internal.h"
#include "upb/port_def.inc"
-#include "upb/table_internal.h"
-/** upb_Message
- * *******************************************************************/
+/** upb_Message ***************************************************************/
static const size_t overhead = sizeof(upb_Message_InternalData);
@@ -55,7 +54,7 @@ static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
upb_Message_Internal* in = upb_Message_Getinternal(msg);
if (!in->internal) {
/* No internal data, allocate from scratch. */
- size_t size = UPB_MAX(128, _upb_Log2Ceilingsize(need + overhead));
+ size_t size = UPB_MAX(128, _upb_Log2CeilingSize(need + overhead));
upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
if (!internal) return false;
internal->size = size;
@@ -64,7 +63,7 @@ static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
in->internal = internal;
} else if (in->internal->ext_begin - in->internal->unknown_end < need) {
/* Internal data is too small, reallocate. */
- size_t new_size = _upb_Log2Ceilingsize(in->internal->size + need);
+ size_t new_size = _upb_Log2CeilingSize(in->internal->size + need);
size_t ext_bytes = in->internal->size - in->internal->ext_begin;
size_t new_ext_begin = new_size - ext_bytes;
upb_Message_InternalData* internal =
@@ -154,7 +153,7 @@ void _upb_Message_Clearext(upb_Message* msg,
}
}
-upb_Message_Extension* _upb_Message_Getorcreateext(
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
upb_Message* msg, const upb_MiniTable_Extension* e, upb_Arena* arena) {
upb_Message_Extension* ext =
(upb_Message_Extension*)_upb_Message_Getext(msg, e);
@@ -310,7 +309,7 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
/* Grow s->entries if necessary. */
if (sorted->end > s->cap) {
- s->cap = _upb_Log2Ceilingsize(sorted->end);
+ s->cap = _upb_Log2CeilingSize(sorted->end);
s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
if (!s->entries) return false;
}
@@ -367,64 +366,3 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
return true;
}
-
-/** upb_ExtensionRegistry
- * ****************************************************************/
-
-struct upb_ExtensionRegistry {
- upb_Arena* arena;
- upb_strtable exts; /* Key is upb_MiniTable* concatenated with fieldnum. */
-};
-
-#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
-
-static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
- memcpy(buf, &l, sizeof(l));
- memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
-}
-
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
- upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
- if (!r) return NULL;
- r->arena = arena;
- if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
- return r;
-}
-
-bool _upb_extreg_add(upb_ExtensionRegistry* r,
- const upb_MiniTable_Extension** e, size_t count) {
- char buf[EXTREG_KEY_SIZE];
- const upb_MiniTable_Extension** start = e;
- const upb_MiniTable_Extension** end = UPB_PTRADD(e, count);
- for (; e < end; e++) {
- const upb_MiniTable_Extension* ext = *e;
- extreg_key(buf, ext->extendee, ext->field.number);
- if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
- upb_value_constptr(ext), r->arena)) {
- goto failure;
- }
- }
- return true;
-
-failure:
- /* Back out the entries previously added. */
- for (end = e, e = start; e < end; e++) {
- const upb_MiniTable_Extension* ext = *e;
- extreg_key(buf, ext->extendee, ext->field.number);
- upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
- }
- return false;
-}
-
-const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
- const upb_MiniTable* l,
- uint32_t num) {
- char buf[EXTREG_KEY_SIZE];
- upb_value v;
- extreg_key(buf, l, num);
- if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
- return upb_value_getconstptr(v);
- } else {
- return NULL;
- }
-}
diff --git a/contrib/libs/grpc/third_party/upb/upb/msg.h b/contrib/libs/grpc/third_party/upb/upb/msg.h
index 99928393ae..5c1e8e8931 100644
--- a/contrib/libs/grpc/third_party/upb/upb/msg.h
+++ b/contrib/libs/grpc/third_party/upb/upb/msg.h
@@ -38,15 +38,14 @@
#include <stddef.h>
+// TODO(b/232091617): Remove this and fix everything that breaks as a result.
+#include "upb/extension_registry.h"
#include "upb/upb.h"
#ifdef __cplusplus
extern "C" {
#endif
-/** upb_Message
- * *******************************************************************/
-
typedef void upb_Message;
/* For users these are opaque. They can be obtained from
@@ -65,49 +64,6 @@ const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
/* Returns the number of extensions present in this message. */
size_t upb_Message_ExtensionCount(const upb_Message* msg);
-/** upb_ExtensionRegistry *****************************************************/
-
-/* Extension registry: a dynamic data structure that stores a map of:
- * (upb_MiniTable, number) -> extension info
- *
- * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
- * binary format.
- *
- * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
- * objects. Like all mini-table objects, it is suitable for reflection-less
- * builds that do not want to expose names into the binary.
- *
- * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
- * allocation and dynamic initialization:
- * * If reflection is being used, then upb_DefPool will construct an appropriate
- * upb_ExtensionRegistry automatically.
- * * For a mini-table only build, the user must manually construct the
- * upb_ExtensionRegistry and populate it with all of the extensions the user
- * cares about.
- * * A third alternative is to manually unpack relevant extensions after the
- * main parse is complete, similar to how Any works. This is perhaps the
- * nicest solution from the perspective of reducing dependencies, avoiding
- * dynamic memory allocation, and avoiding the need to parse uninteresting
- * extensions. The downsides are:
- * (1) parse errors are not caught during the main parse
- * (2) the CPU hit of parsing comes during access, which could cause an
- * undesirable stutter in application performance.
- *
- * Users cannot directly get or put into this map. Users can only add the
- * extensions from a generated module and pass the extension registry to the
- * binary decoder.
- *
- * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
- * reflection do not need to populate a upb_ExtensionRegistry directly.
- */
-
-struct upb_ExtensionRegistry;
-typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
-
-/* Creates a upb_ExtensionRegistry in the given arena. The arena must outlive
- * any use of the extreg. */
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/contrib/libs/grpc/third_party/upb/upb/msg_internal.h b/contrib/libs/grpc/third_party/upb/upb/msg_internal.h
index 88c17108f1..4f5c4797c5 100644
--- a/contrib/libs/grpc/third_party/upb/upb/msg_internal.h
+++ b/contrib/libs/grpc/third_party/upb/upb/msg_internal.h
@@ -39,8 +39,9 @@
#include <stdlib.h>
#include <string.h>
+#include "upb/extension_registry.h"
+#include "upb/internal/table.h"
#include "upb/msg.h"
-#include "upb/table_internal.h"
#include "upb/upb.h"
/* Must be last. */
@@ -50,6 +51,18 @@
extern "C" {
#endif
+/** upb_*Int* conversion routines ********************************************/
+
+UPB_INLINE int32_t _upb_Int32_FromI(int v) { return (int32_t)v; }
+
+UPB_INLINE int64_t _upb_Int64_FromLL(long long v) { return (int64_t)v; }
+
+UPB_INLINE uint32_t _upb_UInt32_FromU(unsigned v) { return (uint32_t)v; }
+
+UPB_INLINE uint64_t _upb_UInt64_FromULL(unsigned long long v) {
+ return (uint64_t)v;
+}
+
/** upb_MiniTable *************************************************************/
/* upb_MiniTable represents the memory layout of a given upb_MessageDef. The
@@ -60,43 +73,40 @@ typedef struct {
uint32_t number;
uint16_t offset;
int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index
- uint16_t submsg_index; // undefined if descriptortype != MESSAGE/GROUP/ENUM
+ uint16_t submsg_index; // kUpb_NoSub if descriptortype != MESSAGE/GROUP/ENUM
uint8_t descriptortype;
uint8_t mode; /* upb_FieldMode | upb_LabelFlags |
- (upb_FieldRep << upb_FieldRep_Shift) */
+ (upb_FieldRep << kUpb_FieldRep_Shift) */
} upb_MiniTable_Field;
+#define kUpb_NoSub ((uint16_t)-1)
+
typedef enum {
kUpb_FieldMode_Map = 0,
kUpb_FieldMode_Array = 1,
kUpb_FieldMode_Scalar = 2,
-
- kUpb_FieldMode_Mask = 3, /* Mask to isolate the mode from upb_FieldRep. */
} upb_FieldMode;
+// Mask to isolate the upb_FieldMode from field.mode.
+#define kUpb_FieldMode_Mask 3
+
/* Extra flags on the mode field. */
-enum upb_LabelFlags {
- upb_LabelFlags_IsPacked = 4,
- upb_LabelFlags_IsExtension = 8,
-};
+typedef enum {
+ kUpb_LabelFlags_IsPacked = 4,
+ kUpb_LabelFlags_IsExtension = 8,
+} upb_LabelFlags;
-/* Representation in the message. Derivable from descriptortype and mode, but
- * fast access helps the serializer. */
-enum upb_FieldRep {
- upb_FieldRep_1Byte = 0,
- upb_FieldRep_4Byte = 1,
- upb_FieldRep_8Byte = 2,
- upb_FieldRep_StringView = 3,
-
-#if UINTPTR_MAX == 0xffffffff
- upb_FieldRep_Pointer = upb_FieldRep_4Byte,
-#else
- upb_FieldRep_Pointer = upb_FieldRep_8Byte,
-#endif
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+ kUpb_FieldRep_1Byte = 0,
+ kUpb_FieldRep_4Byte = 1,
+ kUpb_FieldRep_StringView = 2,
+ kUpb_FieldRep_Pointer = 3,
+ kUpb_FieldRep_8Byte = 4,
- upb_FieldRep_Shift =
- 6, /* Bit offset of the rep in upb_MiniTable_Field.mode */
-};
+ kUpb_FieldRep_Shift = 5, // Bit offset of the rep in upb_MiniTable_Field.mode
+ kUpb_FieldRep_Max = kUpb_FieldRep_8Byte,
+} upb_FieldRep;
UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTable_Field* field) {
return (upb_FieldMode)(field->mode & 3);
@@ -130,36 +140,28 @@ typedef struct {
int value_count;
} upb_MiniTable_Enum;
-UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e,
- int32_t val) {
- uint32_t uval = (uint32_t)val;
- if (uval < 64) return e->mask & (1 << uval);
- // OPT: binary search long lists?
- int n = e->value_count;
- for (int i = 0; i < n; i++) {
- if (e->values[i] == val) return true;
- }
- return false;
-}
-
typedef union {
const struct upb_MiniTable* submsg;
const upb_MiniTable_Enum* subenum;
} upb_MiniTable_Sub;
typedef enum {
- upb_ExtMode_NonExtendable = 0, // Non-extendable message.
- upb_ExtMode_Extendable = 1, // Normal extendable message.
- upb_ExtMode_IsMessageSet = 2, // MessageSet message.
- upb_ExtMode_IsMessageSet_ITEM =
+ kUpb_ExtMode_NonExtendable = 0, // Non-extendable message.
+ kUpb_ExtMode_Extendable = 1, // Normal extendable message.
+ kUpb_ExtMode_IsMessageSet = 2, // MessageSet message.
+ kUpb_ExtMode_IsMessageSet_ITEM =
3, // MessageSet item (temporary only, see decode.c)
+
+ // During table building we steal a bit to indicate that the message is a map
+ // entry. *Only* used during table building!
+ kUpb_ExtMode_IsMapEntry = 4,
} upb_ExtMode;
/* MessageSet wire format is:
* message MessageSet {
* repeated group Item = 1 {
* required int32 type_id = 2;
- * required string message = 3;
+ * required bytes message = 3;
* }
* }
*/
@@ -213,8 +215,7 @@ UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
return ((1ULL << n) - 1) << 1;
}
-/** upb_ExtensionRegistry
- * ****************************************************************/
+/** upb_ExtensionRegistry *****************************************************/
/* Adds the given extension info for message type |l| and field number |num|
* into the registry. Returns false if this message type and field number were
@@ -229,8 +230,7 @@ const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
const upb_MiniTable* l,
uint32_t num);
-/** upb_Message
- * *******************************************************************/
+/** upb_Message ***************************************************************/
/* Internal members of a upb_Message that track unknown fields and/or
* extensions. We can change this without breaking binary compatibility. We put
@@ -276,7 +276,7 @@ UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* l) {
UPB_INLINE upb_Message* _upb_Message_New_inl(const upb_MiniTable* l,
upb_Arena* a) {
size_t size = upb_msg_sizeof(l);
- void* mem = upb_Arena_Malloc(a, size);
+ void* mem = upb_Arena_Malloc(a, size + sizeof(upb_Message_Internal));
upb_Message* msg;
if (UPB_UNLIKELY(!mem)) return NULL;
msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
@@ -303,8 +303,7 @@ void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
upb_Arena* arena);
-/** upb_Message_Extension
- * ***************************************************************/
+/** upb_Message_Extension *****************************************************/
/* The internal representation of an extension is self-describing: it contains
* enough information that we can serialize it to binary format without needing
@@ -326,7 +325,7 @@ typedef struct {
/* Adds the given extension data to the given message. |ext| is copied into the
* message instance. This logically replaces any previously-added extension with
* this number */
-upb_Message_Extension* _upb_Message_Getorcreateext(
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
upb_Message* msg, const upb_MiniTable_Extension* ext, upb_Arena* arena);
/* Returns an array of extensions for this message. Note: the array is
@@ -472,6 +471,10 @@ UPB_INLINE bool _upb_Array_Resize(upb_Array* arr, size_t size,
return true;
}
+UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) {
+ *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL;
+}
+
UPB_INLINE const void* _upb_array_accessor(const void* msg, size_t ofs,
size_t* size) {
const upb_Array* arr = *UPB_PTR_AT(msg, ofs, const upb_Array*);
@@ -665,15 +668,31 @@ UPB_INLINE void* _upb_map_next(const upb_Map* map, size_t* iter) {
return (void*)str_tabent(&it);
}
-UPB_INLINE bool _upb_Map_Set(upb_Map* map, const void* key, size_t key_size,
- void* val, size_t val_size, upb_Arena* a) {
+typedef enum {
+ // LINT.IfChange
+ _kUpb_MapInsertStatus_Inserted = 0,
+ _kUpb_MapInsertStatus_Replaced = 1,
+ _kUpb_MapInsertStatus_OutOfMemory = 2,
+ // LINT.ThenChange(//depot/google3/third_party/upb/upb/map.h)
+} _upb_MapInsertStatus;
+
+UPB_INLINE _upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key,
+ size_t key_size, void* val,
+ size_t val_size, upb_Arena* a) {
upb_StringView strkey = _upb_map_tokey(key, key_size);
upb_value tabval = {0};
- if (!_upb_map_tovalue(val, val_size, &tabval, a)) return false;
+ if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
+ return _kUpb_MapInsertStatus_OutOfMemory;
+ }
/* TODO(haberman): add overwrite operation to minimize number of lookups. */
- upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
- return upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a);
+ bool removed =
+ upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
+ if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) {
+ return _kUpb_MapInsertStatus_OutOfMemory;
+ }
+ return removed ? _kUpb_MapInsertStatus_Replaced
+ : _kUpb_MapInsertStatus_Inserted;
}
UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key,
@@ -715,7 +734,8 @@ UPB_INLINE bool _upb_msg_map_set(upb_Message* msg, size_t ofs, const void* key,
if (!*map) {
*map = _upb_Map_New(arena, key_size, val_size);
}
- return _upb_Map_Set(*map, key, key_size, val, val_size, arena);
+ return _upb_Map_Insert(*map, key, key_size, val, val_size, arena) !=
+ _kUpb_MapInsertStatus_OutOfMemory;
}
UPB_INLINE bool _upb_msg_map_delete(upb_Message* msg, size_t ofs,
@@ -761,8 +781,7 @@ UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val,
}
}
-/** _upb_mapsorter
- * *************************************************************/
+/** _upb_mapsorter ************************************************************/
/* _upb_mapsorter sorts maps and provides ordered iteration over the entries.
* Since maps can be recursive (map values can be messages which contain other
diff --git a/contrib/libs/grpc/third_party/upb/upb/port_def.inc b/contrib/libs/grpc/third_party/upb/upb/port_def.inc
index 75d416d1ce..92e4bf2477 100644
--- a/contrib/libs/grpc/third_party/upb/upb/port_def.inc
+++ b/contrib/libs/grpc/third_party/upb/upb/port_def.inc
@@ -88,9 +88,10 @@
#define UPB_INLINE static
#endif
+#define UPB_MALLOC_ALIGN 8
#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
-#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
/* Hints to the compiler about likely/unlikely branches. */
@@ -251,3 +252,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
((void)(addr), (void)(size))
#endif
+
+/* Disable proto2 arena behavior (TEMPORARY) **********************************/
+
+#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1
+#else
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0
+#endif
diff --git a/contrib/libs/grpc/third_party/upb/upb/port_undef.inc b/contrib/libs/grpc/third_party/upb/upb/port_undef.inc
index 70956df25d..1dff3d275d 100644
--- a/contrib/libs/grpc/third_party/upb/upb/port_undef.inc
+++ b/contrib/libs/grpc/third_party/upb/upb/port_undef.inc
@@ -37,6 +37,7 @@
#undef UPB_ALIGN_DOWN
#undef UPB_ALIGN_MALLOC
#undef UPB_ALIGN_OF
+#undef UPB_MALLOC_ALIGN
#undef UPB_LIKELY
#undef UPB_UNLIKELY
#undef UPB_FORCEINLINE
@@ -59,3 +60,4 @@
#undef UPB_POISON_MEMORY_REGION
#undef UPB_UNPOISON_MEMORY_REGION
#undef UPB_ASAN
+#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3
diff --git a/contrib/libs/grpc/third_party/upb/upb/reflection.c b/contrib/libs/grpc/third_party/upb/upb/reflection.c
index a3a64d2780..43f884495f 100644
--- a/contrib/libs/grpc/third_party/upb/upb/reflection.c
+++ b/contrib/libs/grpc/third_party/upb/upb/reflection.c
@@ -29,9 +29,9 @@
#include <string.h>
+#include "upb/internal/table.h"
#include "upb/msg.h"
#include "upb/port_def.inc"
-#include "upb/table_internal.h"
static size_t get_field_size(const upb_MiniTable_Field* f) {
static unsigned char sizes[] = {
@@ -58,37 +58,6 @@ static size_t get_field_size(const upb_MiniTable_Field* f) {
return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
}
-/* Strings/bytes are special-cased in maps. */
-static char _upb_CTypeo_mapsize[12] = {
- 0,
- 1, /* kUpb_CType_Bool */
- 4, /* kUpb_CType_Float */
- 4, /* kUpb_CType_Int32 */
- 4, /* kUpb_CType_UInt32 */
- 4, /* kUpb_CType_Enum */
- sizeof(void*), /* kUpb_CType_Message */
- 8, /* kUpb_CType_Double */
- 8, /* kUpb_CType_Int64 */
- 8, /* kUpb_CType_UInt64 */
- 0, /* kUpb_CType_String */
- 0, /* kUpb_CType_Bytes */
-};
-
-static const char _upb_CTypeo_sizelg2[12] = {
- 0,
- 0, /* kUpb_CType_Bool */
- 2, /* kUpb_CType_Float */
- 2, /* kUpb_CType_Int32 */
- 2, /* kUpb_CType_UInt32 */
- 2, /* kUpb_CType_Enum */
- UPB_SIZE(2, 3), /* kUpb_CType_Message */
- 3, /* kUpb_CType_Double */
- 3, /* kUpb_CType_Int64 */
- 3, /* kUpb_CType_UInt64 */
- UPB_SIZE(3, 4), /* kUpb_CType_String */
- UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
-};
-
/** upb_Message
* *******************************************************************/
@@ -202,7 +171,7 @@ make:
bool upb_Message_Set(upb_Message* msg, const upb_FieldDef* f,
upb_MessageValue val, upb_Arena* a) {
if (upb_FieldDef_IsExtension(f)) {
- upb_Message_Extension* ext = _upb_Message_Getorcreateext(
+ upb_Message_Extension* ext = _upb_Message_GetOrCreateExtension(
msg, _upb_FieldDef_ExtensionMiniTable(f), a);
if (!ext) return false;
memcpy(&ext->data, &val, sizeof(val));
@@ -352,129 +321,3 @@ bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
int maxdepth) {
return _upb_Message_DiscardUnknown(msg, m, maxdepth);
}
-
-/** upb_Array *****************************************************************/
-
-upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
- return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
-}
-
-size_t upb_Array_Size(const upb_Array* arr) { return arr->len; }
-
-upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
- upb_MessageValue ret;
- const char* data = _upb_array_constptr(arr);
- int lg2 = arr->data & 7;
- UPB_ASSERT(i < arr->len);
- memcpy(&ret, data + (i << lg2), 1 << lg2);
- return ret;
-}
-
-void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
- char* data = _upb_array_ptr(arr);
- int lg2 = arr->data & 7;
- UPB_ASSERT(i < arr->len);
- memcpy(data + (i << lg2), &val, 1 << lg2);
-}
-
-bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
- if (!upb_Array_Resize(arr, arr->len + 1, arena)) {
- return false;
- }
- upb_Array_Set(arr, arr->len - 1, val);
- return true;
-}
-
-void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
- size_t count) {
- char* data = _upb_array_ptr(arr);
- int lg2 = arr->data & 7;
- memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
-}
-
-bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
- upb_Arena* arena) {
- UPB_ASSERT(i <= arr->len);
- UPB_ASSERT(count + arr->len >= count);
- size_t oldsize = arr->len;
- if (!upb_Array_Resize(arr, arr->len + count, arena)) {
- return false;
- }
- upb_Array_Move(arr, i + count, i, oldsize - i);
- return true;
-}
-
-/*
- * i end arr->len
- * |------------|XXXXXXXX|--------|
- */
-void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
- size_t end = i + count;
- UPB_ASSERT(i <= end);
- UPB_ASSERT(end <= arr->len);
- upb_Array_Move(arr, i, end, arr->len - end);
- arr->len -= count;
-}
-
-bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
- return _upb_Array_Resize(arr, size, arena);
-}
-
-/** upb_Map *******************************************************************/
-
-upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) {
- return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
- _upb_CTypeo_mapsize[value_type]);
-}
-
-size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); }
-
-bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
- upb_MessageValue* val) {
- return _upb_Map_Get(map, &key, map->key_size, val, map->val_size);
-}
-
-void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); }
-
-bool upb_Map_Set(upb_Map* map, upb_MessageValue key, upb_MessageValue val,
- upb_Arena* arena) {
- return _upb_Map_Set(map, &key, map->key_size, &val, map->val_size, arena);
-}
-
-bool upb_Map_Delete(upb_Map* map, upb_MessageValue key) {
- return _upb_Map_Delete(map, &key, map->key_size);
-}
-
-bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
- return _upb_map_next(map, iter);
-}
-
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
- upb_strtable_iter i;
- UPB_ASSERT(iter != kUpb_Map_Begin);
- i.t = &map->table;
- i.index = iter;
- return upb_strtable_done(&i);
-}
-
-/* Returns the key and value for this entry of the map. */
-upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
- upb_strtable_iter i;
- upb_MessageValue ret;
- i.t = &map->table;
- i.index = iter;
- _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
- return ret;
-}
-
-upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
- upb_strtable_iter i;
- upb_MessageValue ret;
- i.t = &map->table;
- i.index = iter;
- _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
- return ret;
-}
-
-/* void upb_MapIterator_SetValue(upb_Map *map, size_t iter, upb_MessageValue
- * value); */
diff --git a/contrib/libs/grpc/third_party/upb/upb/reflection.h b/contrib/libs/grpc/third_party/upb/upb/reflection.h
index b892f66bfb..6071fba6f5 100644
--- a/contrib/libs/grpc/third_party/upb/upb/reflection.h
+++ b/contrib/libs/grpc/third_party/upb/upb/reflection.h
@@ -28,7 +28,9 @@
#ifndef UPB_REFLECTION_H_
#define UPB_REFLECTION_H_
+#include "upb/array.h"
#include "upb/def.h"
+#include "upb/map.h"
#include "upb/msg.h"
#include "upb/port_def.inc"
#include "upb/upb.h"
@@ -37,26 +39,6 @@
extern "C" {
#endif
-typedef union {
- bool bool_val;
- float float_val;
- double double_val;
- int32_t int32_val;
- int64_t int64_val;
- uint32_t uint32_val;
- uint64_t uint64_val;
- const upb_Map* map_val;
- const upb_Message* msg_val;
- const upb_Array* array_val;
- upb_StringView str_val;
-} upb_MessageValue;
-
-typedef union {
- upb_Map* map;
- upb_Message* msg;
- upb_Array* array;
-} upb_MutableMessageValue;
-
upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f);
/** upb_Message
@@ -119,98 +101,6 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
int maxdepth);
-/** upb_Array *****************************************************************/
-
-/* Creates a new array on the given arena that holds elements of this type. */
-upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
-
-/* Returns the size of the array. */
-size_t upb_Array_Size(const upb_Array* arr);
-
-/* Returns the given element, which must be within the array's current size. */
-upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i);
-
-/* Sets the given element, which must be within the array's current size. */
-void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val);
-
-/* Appends an element to the array. Returns false on allocation failure. */
-bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
-
-/* Moves elements within the array using memmove(). Like memmove(), the source
- * and destination elements may be overlapping. */
-void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
- size_t count);
-
-/* Inserts one or more empty elements into the array. Existing elements are
- * shifted right. The new elements have undefined state and must be set with
- * `upb_Array_Set()`.
- * REQUIRES: `i <= upb_Array_Size(arr)` */
-bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
- upb_Arena* arena);
-
-/* Deletes one or more elements from the array. Existing elements are shifted
- * left.
- * REQUIRES: `i + count <= upb_Array_Size(arr)` */
-void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
-
-/* Changes the size of a vector. New elements are initialized to empty/0.
- * Returns false on allocation failure. */
-bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena);
-
-/** upb_Map *******************************************************************/
-
-/* Creates a new map on the given arena with the given key/value size. */
-upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type);
-
-/* Returns the number of entries in the map. */
-size_t upb_Map_Size(const upb_Map* map);
-
-/* Stores a value for the given key into |*val| (or the zero value if the key is
- * not present). Returns whether the key was present. The |val| pointer may be
- * NULL, in which case the function tests whether the given key is present. */
-bool upb_Map_Get(const upb_Map* map, upb_MessageValue key,
- upb_MessageValue* val);
-
-/* Removes all entries in the map. */
-void upb_Map_Clear(upb_Map* map);
-
-/* Sets the given key to the given value. Returns true if this was a new key in
- * the map, or false if an existing key was replaced. */
-bool upb_Map_Set(upb_Map* map, upb_MessageValue key, upb_MessageValue val,
- upb_Arena* arena);
-
-/* Deletes this key from the table. Returns true if the key was present. */
-bool upb_Map_Delete(upb_Map* map, upb_MessageValue key);
-
-/* Map iteration:
- *
- * size_t iter = kUpb_Map_Begin;
- * while (upb_MapIterator_Next(map, &iter)) {
- * upb_MessageValue key = upb_MapIterator_Key(map, iter);
- * upb_MessageValue val = upb_MapIterator_Value(map, iter);
- *
- * // If mutating is desired.
- * upb_MapIterator_SetValue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry. Returns false if no more entries are present. */
-bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
-
-/* Returns true if the iterator still points to a valid entry, or false if the
- * iterator is past the last element. It is an error to call this function with
- * kUpb_Map_Begin (you must call next() at least once first). */
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
-upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
-
-/* Sets the value for this entry. The iterator must not be done, and the
- * iterator must not have been initialized const. */
-void upb_MapIterator_SetValue(upb_Map* map, size_t iter,
- upb_MessageValue value);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/contrib/libs/grpc/third_party/upb/upb/status.c b/contrib/libs/grpc/third_party/upb/upb/status.c
new file mode 100644
index 0000000000..c00b9c86b2
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/status.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 "upb/status.h"
+
+#include <errno.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "upb/internal/upb.h"
+
+// Must be last.
+#include "upb/port_def.inc"
+
+void upb_Status_Clear(upb_Status* status) {
+ if (!status) return;
+ status->ok = true;
+ status->msg[0] = '\0';
+}
+
+bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
+
+const char* upb_Status_ErrorMessage(const upb_Status* status) {
+ return status->msg;
+}
+
+void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
+ if (!status) return;
+ status->ok = false;
+ strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
+ status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
+}
+
+void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ upb_Status_VSetErrorFormat(status, fmt, args);
+ va_end(args);
+}
+
+void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
+ va_list args) {
+ if (!status) return;
+ status->ok = false;
+ vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+ status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
+}
+
+void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
+ va_list args) {
+ size_t len;
+ if (!status) return;
+ status->ok = false;
+ len = strlen(status->msg);
+ vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+ status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/status.h b/contrib/libs/grpc/third_party/upb/upb/status.h
new file mode 100644
index 0000000000..2c5c2a7f8b
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/status.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2009-2021, Google LLC
+ * 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 LLC 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 Google LLC 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 UPB_STATUS_H_
+#define UPB_STATUS_H_
+
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _kUpb_Status_MaxMessage 127
+
+typedef struct {
+ bool ok;
+ char msg[_kUpb_Status_MaxMessage]; /* Error message; NULL-terminated. */
+} upb_Status;
+
+const char* upb_Status_ErrorMessage(const upb_Status* status);
+bool upb_Status_IsOk(const upb_Status* status);
+
+/* These are no-op if |status| is NULL. */
+void upb_Status_Clear(upb_Status* status);
+void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
+void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
+ UPB_PRINTF(2, 3);
+void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
+ va_list args) UPB_PRINTF(2, 0);
+void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
+ va_list args) UPB_PRINTF(2, 0);
+
+#include "upb/port_undef.inc"
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_STATUS_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/table.c b/contrib/libs/grpc/third_party/upb/upb/table.c
index 33b3a9dc6e..e8e55f7e34 100644
--- a/contrib/libs/grpc/third_party/upb/upb/table.c
+++ b/contrib/libs/grpc/third_party/upb/upb/table.c
@@ -31,9 +31,9 @@
* Implementation is heavily inspired by Lua's ltable.c.
*/
-#include <string.h>
+#include "upb/internal/table.h"
-#include "upb/table_internal.h"
+#include <string.h>
/* Must be last. */
#include "upb/port_def.inc"
@@ -433,14 +433,18 @@ const uint64_t kWyhashSalt[5] = {
0x082EFA98EC4E6C89ULL, 0x452821E638D01377ULL,
};
-static uint32_t table_hash(const char* p, size_t n) {
- return Wyhash(p, n, 0, kWyhashSalt);
+uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed) {
+ return Wyhash(p, n, seed, kWyhashSalt);
+}
+
+static uint32_t _upb_Hash_NoSeed(const char* p, size_t n) {
+ return _upb_Hash(p, n, 0);
}
static uint32_t strhash(upb_tabkey key) {
uint32_t len;
char* str = upb_tabstr(key, &len);
- return table_hash(str, len);
+ return _upb_Hash_NoSeed(str, len);
}
static bool streql(upb_tabkey k1, lookupkey_t k2) {
@@ -496,20 +500,20 @@ bool upb_strtable_insert(upb_strtable* t, const char* k, size_t len,
tabkey = strcopy(key, a);
if (tabkey == 0) return false;
- hash = table_hash(key.str.str, key.str.len);
+ hash = _upb_Hash_NoSeed(key.str.str, key.str.len);
insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
return true;
}
bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
upb_value* v) {
- uint32_t hash = table_hash(key, len);
+ uint32_t hash = _upb_Hash_NoSeed(key, len);
return lookup(&t->t, strkey2(key, len), v, hash, &streql);
}
bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len,
upb_value* val) {
- uint32_t hash = table_hash(key, len);
+ uint32_t hash = _upb_Hash_NoSeed(key, len);
upb_tabkey tabkey;
return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
}
diff --git a/contrib/libs/grpc/third_party/upb/upb/text_encode.c b/contrib/libs/grpc/third_party/upb/upb/text_encode.c
index 9612375dba..dfb213f2bb 100644
--- a/contrib/libs/grpc/third_party/upb/upb/text_encode.c
+++ b/contrib/libs/grpc/third_party/upb/upb/text_encode.c
@@ -34,8 +34,9 @@
#include <stdio.h>
#include <string.h>
+#include "upb/internal/upb.h"
+#include "upb/internal/vsnprintf_compat.h"
#include "upb/reflection.h"
-#include "upb/upb_internal.h"
// Must be last.
#include "upb/port_def.inc"
@@ -76,7 +77,7 @@ static void txtenc_printf(txtenc* e, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
- n = vsnprintf(e->ptr, have, fmt, args);
+ n = _upb_vsnprintf(e->ptr, have, fmt, args);
va_end(args);
if (UPB_LIKELY(have > n)) {
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.c b/contrib/libs/grpc/third_party/upb/upb/upb.c
index 55730bbe82..08ae964777 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb.c
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.c
@@ -25,6 +25,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "upb/internal/upb.h"
+
#include <errno.h>
#include <float.h>
#include <stdarg.h>
@@ -34,300 +36,12 @@
#include <stdlib.h>
#include <string.h>
-#include "upb/upb_internal.h"
+#include "upb/arena.h"
+#include "upb/status.h"
// Must be last.
#include "upb/port_def.inc"
-/* upb_Status *****************************************************************/
-
-void upb_Status_Clear(upb_Status* status) {
- if (!status) return;
- status->ok = true;
- status->msg[0] = '\0';
-}
-
-bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
-
-const char* upb_Status_ErrorMessage(const upb_Status* status) {
- return status->msg;
-}
-
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
- if (!status) return;
- status->ok = false;
- strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
- status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- upb_Status_VSetErrorFormat(status, fmt, args);
- va_end(args);
-}
-
-void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
- va_list args) {
- if (!status) return;
- status->ok = false;
- vsnprintf(status->msg, sizeof(status->msg), fmt, args);
- status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
- va_list args) {
- size_t len;
- if (!status) return;
- status->ok = false;
- len = strlen(status->msg);
- vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
- status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-/* upb_alloc ******************************************************************/
-
-static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize,
- size_t size) {
- UPB_UNUSED(alloc);
- UPB_UNUSED(oldsize);
- if (size == 0) {
- free(ptr);
- return NULL;
- } else {
- return realloc(ptr, size);
- }
-}
-
-static uint32_t* upb_cleanup_pointer(uintptr_t cleanup_metadata) {
- return (uint32_t*)(cleanup_metadata & ~0x1);
-}
-
-static bool upb_cleanup_has_initial_block(uintptr_t cleanup_metadata) {
- return cleanup_metadata & 0x1;
-}
-
-static uintptr_t upb_cleanup_metadata(uint32_t* cleanup,
- bool has_initial_block) {
- return (uintptr_t)cleanup | has_initial_block;
-}
-
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
-
-/* upb_Arena ******************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-
-struct mem_block {
- struct mem_block* next;
- uint32_t size;
- uint32_t cleanups;
- /* Data follows. */
-};
-
-typedef struct cleanup_ent {
- upb_CleanupFunc* cleanup;
- void* ud;
-} cleanup_ent;
-
-static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
-
-static upb_Arena* arena_findroot(upb_Arena* a) {
- /* Path splitting keeps time complexity down, see:
- * https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
- while (a->parent != a) {
- upb_Arena* next = a->parent;
- a->parent = next->parent;
- a = next;
- }
- return a;
-}
-
-static void upb_Arena_addblock(upb_Arena* a, upb_Arena* root, void* ptr,
- size_t size) {
- mem_block* block = ptr;
-
- /* The block is for arena |a|, but should appear in the freelist of |root|. */
- block->next = root->freelist;
- block->size = (uint32_t)size;
- block->cleanups = 0;
- root->freelist = block;
- a->last_size = block->size;
- if (!root->freelist_tail) root->freelist_tail = block;
-
- a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
- a->head.end = UPB_PTR_AT(block, size, char);
- a->cleanup_metadata = upb_cleanup_metadata(
- &block->cleanups, upb_cleanup_has_initial_block(a->cleanup_metadata));
-
- UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
-}
-
-static bool upb_Arena_Allocblock(upb_Arena* a, size_t size) {
- upb_Arena* root = arena_findroot(a);
- size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
- mem_block* block = upb_malloc(root->block_alloc, block_size);
-
- if (!block) return false;
- upb_Arena_addblock(a, root, block, block_size);
- return true;
-}
-
-void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size) {
- if (!upb_Arena_Allocblock(a, size)) return NULL; /* Out of memory. */
- UPB_ASSERT(_upb_ArenaHas(a) >= size);
- return upb_Arena_Malloc(a, size);
-}
-
-static void* upb_Arena_doalloc(upb_alloc* alloc, void* ptr, size_t oldsize,
- size_t size) {
- upb_Arena* a = (upb_Arena*)alloc; /* upb_alloc is initial member. */
- return upb_Arena_Realloc(a, ptr, oldsize, size);
-}
-
-/* Public Arena API ***********************************************************/
-
-upb_Arena* arena_initslow(void* mem, size_t n, upb_alloc* alloc) {
- const size_t first_block_overhead = sizeof(upb_Arena) + memblock_reserve;
- upb_Arena* a;
-
- /* We need to malloc the initial block. */
- n = first_block_overhead + 256;
- if (!alloc || !(mem = upb_malloc(alloc, n))) {
- return NULL;
- }
-
- a = UPB_PTR_AT(mem, n - sizeof(*a), upb_Arena);
- n -= sizeof(*a);
-
- a->head.alloc.func = &upb_Arena_doalloc;
- a->block_alloc = alloc;
- a->parent = a;
- a->refcount = 1;
- a->freelist = NULL;
- a->freelist_tail = NULL;
- a->cleanup_metadata = upb_cleanup_metadata(NULL, false);
-
- upb_Arena_addblock(a, a, mem, n);
-
- return a;
-}
-
-upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
- upb_Arena* a;
-
- if (n) {
- /* Align initial pointer up so that we return properly-aligned pointers. */
- void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, 16);
- size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
- n = delta <= n ? n - delta : 0;
- mem = aligned;
- }
-
- /* Round block size down to alignof(*a) since we will allocate the arena
- * itself at the end. */
- n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_Arena));
-
- if (UPB_UNLIKELY(n < sizeof(upb_Arena))) {
- return arena_initslow(mem, n, alloc);
- }
-
- a = UPB_PTR_AT(mem, n - sizeof(*a), upb_Arena);
-
- a->head.alloc.func = &upb_Arena_doalloc;
- a->block_alloc = alloc;
- a->parent = a;
- a->refcount = 1;
- a->last_size = UPB_MAX(128, n);
- a->head.ptr = mem;
- a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
- a->freelist = NULL;
- a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
-
- return a;
-}
-
-static void arena_dofree(upb_Arena* a) {
- mem_block* block = a->freelist;
- UPB_ASSERT(a->parent == a);
- UPB_ASSERT(a->refcount == 0);
-
- while (block) {
- /* Load first since we are deleting block. */
- mem_block* next = block->next;
-
- if (block->cleanups > 0) {
- cleanup_ent* end = UPB_PTR_AT(block, block->size, void);
- cleanup_ent* ptr = end - block->cleanups;
-
- for (; ptr < end; ptr++) {
- ptr->cleanup(ptr->ud);
- }
- }
-
- upb_free(a->block_alloc, block);
- block = next;
- }
-}
-
-void upb_Arena_Free(upb_Arena* a) {
- a = arena_findroot(a);
- if (--a->refcount == 0) arena_dofree(a);
-}
-
-bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func) {
- cleanup_ent* ent;
- uint32_t* cleanups = upb_cleanup_pointer(a->cleanup_metadata);
-
- if (!cleanups || _upb_ArenaHas(a) < sizeof(cleanup_ent)) {
- if (!upb_Arena_Allocblock(a, 128)) return false; /* Out of memory. */
- UPB_ASSERT(_upb_ArenaHas(a) >= sizeof(cleanup_ent));
- cleanups = upb_cleanup_pointer(a->cleanup_metadata);
- }
-
- a->head.end -= sizeof(cleanup_ent);
- ent = (cleanup_ent*)a->head.end;
- (*cleanups)++;
- UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
-
- ent->cleanup = func;
- ent->ud = ud;
-
- return true;
-}
-
-bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) {
- upb_Arena* r1 = arena_findroot(a1);
- upb_Arena* r2 = arena_findroot(a2);
-
- if (r1 == r2) return true; /* Already fused. */
-
- /* Do not fuse initial blocks since we cannot lifetime extend them. */
- if (upb_cleanup_has_initial_block(r1->cleanup_metadata)) return false;
- if (upb_cleanup_has_initial_block(r2->cleanup_metadata)) return false;
-
- /* Only allow fuse with a common allocator */
- if (r1->block_alloc != r2->block_alloc) return false;
-
- /* We want to join the smaller tree to the larger tree.
- * So swap first if they are backwards. */
- if (r1->refcount < r2->refcount) {
- upb_Arena* tmp = r1;
- r1 = r2;
- r2 = tmp;
- }
-
- /* r1 takes over r2's freelist and refcount. */
- r1->refcount += r2->refcount;
- if (r2->freelist_tail) {
- UPB_ASSERT(r2->freelist_tail->next == NULL);
- r2->freelist_tail->next = r1->freelist;
- r1->freelist = r2->freelist;
- }
- r2->parent = r1;
- return true;
-}
-
/* Miscellaneous utilities ****************************************************/
static void upb_FixLocale(char* p) {
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.h b/contrib/libs/grpc/third_party/upb/upb/upb.h
index 12aecb46cb..7398d09fff 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb.h
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.h
@@ -39,34 +39,17 @@
#include <stdint.h>
#include <string.h>
+// TODO(b/232091617): Remove these and fix everything that breaks as a result.
+#include "upb/arena.h"
+#include "upb/status.h"
+
+// Must be last.
#include "upb/port_def.inc"
#ifdef __cplusplus
extern "C" {
#endif
-/* upb_Status *****************************************************************/
-
-#define _kUpb_Status_MaxMessage 127
-
-typedef struct {
- bool ok;
- char msg[_kUpb_Status_MaxMessage]; /* Error message; NULL-terminated. */
-} upb_Status;
-
-const char* upb_Status_ErrorMessage(const upb_Status* status);
-bool upb_Status_IsOk(const upb_Status* status);
-
-/* These are no-op if |status| is NULL. */
-void upb_Status_Clear(upb_Status* status);
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
- UPB_PRINTF(2, 3);
-void upb_Status_VSetErrorFormat(upb_Status* status, const char* fmt,
- va_list args) UPB_PRINTF(2, 0);
-void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
- va_list args) UPB_PRINTF(2, 0);
-
/** upb_StringView ************************************************************/
typedef struct {
@@ -96,148 +79,6 @@ UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) {
#define UPB_STRINGVIEW_FORMAT "%.*s"
#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
-/** upb_alloc *****************************************************************/
-
-/* A upb_alloc is a possibly-stateful allocator object.
- *
- * It could either be an arena allocator (which doesn't require individual
- * free() calls) or a regular malloc() (which does). The client must therefore
- * free memory unless it knows that the allocator is an arena allocator. */
-
-struct upb_alloc;
-typedef struct upb_alloc upb_alloc;
-
-/* A malloc()/free() function.
- * If "size" is 0 then the function acts like free(), otherwise it acts like
- * realloc(). Only "oldsize" bytes from a previous allocation are preserved. */
-typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize,
- size_t size);
-
-struct upb_alloc {
- upb_alloc_func* func;
-};
-
-UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) {
- UPB_ASSERT(alloc);
- return alloc->func(alloc, NULL, 0, size);
-}
-
-UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize,
- size_t size) {
- UPB_ASSERT(alloc);
- return alloc->func(alloc, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) {
- assert(alloc);
- alloc->func(alloc, ptr, 0, 0);
-}
-
-/* The global allocator used by upb. Uses the standard malloc()/free(). */
-
-extern upb_alloc upb_alloc_global;
-
-/* Functions that hard-code the global malloc.
- *
- * We still get benefit because we can put custom logic into our global
- * allocator, like injecting out-of-memory faults in debug/testing builds. */
-
-UPB_INLINE void* upb_gmalloc(size_t size) {
- return upb_malloc(&upb_alloc_global, size);
-}
-
-UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) {
- return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); }
-
-/* upb_Arena ******************************************************************/
-
-/* upb_Arena is a specific allocator implementation that uses arena allocation.
- * The user provides an allocator that will be used to allocate the underlying
- * arena blocks. Arenas by nature do not require the individual allocations
- * to be freed. However the Arena does allow users to register cleanup
- * functions that will run when the arena is destroyed.
- *
- * A upb_Arena is *not* thread-safe.
- *
- * You could write a thread-safe arena allocator that satisfies the
- * upb_alloc interface, but it would not be as efficient for the
- * single-threaded case. */
-
-typedef void upb_CleanupFunc(void* ud);
-
-struct upb_Arena;
-typedef struct upb_Arena upb_Arena;
-
-typedef struct {
- /* We implement the allocator interface.
- * This must be the first member of upb_Arena!
- * TODO(haberman): remove once handlers are gone. */
- upb_alloc alloc;
-
- char *ptr, *end;
-} _upb_ArenaHead;
-
-/* Creates an arena from the given initial block (if any -- n may be 0).
- * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
- * is a fixed-size arena and cannot grow. */
-upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc);
-void upb_Arena_Free(upb_Arena* a);
-bool upb_Arena_AddCleanup(upb_Arena* a, void* ud, upb_CleanupFunc* func);
-bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b);
-void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size);
-
-UPB_INLINE upb_alloc* upb_Arena_Alloc(upb_Arena* a) { return (upb_alloc*)a; }
-
-UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
- _upb_ArenaHead* h = (_upb_ArenaHead*)a;
- return (size_t)(h->end - h->ptr);
-}
-
-UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
- _upb_ArenaHead* h = (_upb_ArenaHead*)a;
- void* ret;
- size = UPB_ALIGN_MALLOC(size);
-
- if (UPB_UNLIKELY(_upb_ArenaHas(a) < size)) {
- return _upb_Arena_SlowMalloc(a, size);
- }
-
- ret = h->ptr;
- h->ptr += size;
- UPB_UNPOISON_MEMORY_REGION(ret, size);
-
-#if UPB_ASAN
- {
- size_t guard_size = 32;
- if (_upb_ArenaHas(a) >= guard_size) {
- h->ptr += guard_size;
- } else {
- h->ptr = h->end;
- }
- }
-#endif
-
- return ret;
-}
-
-UPB_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize,
- size_t size) {
- void* ret = upb_Arena_Malloc(a, size);
-
- if (ret && oldsize > 0) {
- memcpy(ret, ptr, oldsize);
- }
-
- return ret;
-}
-
-UPB_INLINE upb_Arena* upb_Arena_New(void) {
- return upb_Arena_Init(NULL, 0, &upb_alloc_global);
-}
-
/* Constants ******************************************************************/
/* A list of types as they are encoded on-the-wire. */
@@ -316,8 +157,8 @@ UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
if (_upb_IsLittleEndian()) {
return val;
} else {
- return ((uint64_t)_upb_BigEndian_Swap32(val) << 32) |
- _upb_BigEndian_Swap32(val >> 32);
+ return ((uint64_t)_upb_BigEndian_Swap32((uint32_t)val) << 32) |
+ _upb_BigEndian_Swap32((uint32_t)(val >> 32));
}
}
@@ -332,7 +173,7 @@ UPB_INLINE int _upb_Log2Ceiling(int x) {
#endif
}
-UPB_INLINE int _upb_Log2Ceilingsize(int x) { return 1 << _upb_Log2Ceiling(x); }
+UPB_INLINE int _upb_Log2CeilingSize(int x) { return 1 << _upb_Log2Ceiling(x); }
#include "upb/port_undef.inc"