aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/grpc/third_party
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-15 21:33:41 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-15 21:33:41 +0300
commit3dd665b514943f69657b593eb51af90b99b1206b (patch)
tree0eb633e628bb1fe6c639574b1184d43def7c0a73 /contrib/libs/grpc/third_party
parenta68afc731202027f105bc5723ee11788017c29e2 (diff)
downloadydb-3dd665b514943f69657b593eb51af90b99b1206b.tar.gz
intermediate changes
ref:953ca886ec160075b38c0f3614de029b423f0a9e
Diffstat (limited to 'contrib/libs/grpc/third_party')
-rw-r--r--contrib/libs/grpc/third_party/ABSEIL_MANUAL.md32
-rw-r--r--contrib/libs/grpc/third_party/README.md8
-rw-r--r--contrib/libs/grpc/third_party/address_sorting/include/address_sorting/address_sorting.h2
-rw-r--r--contrib/libs/grpc/third_party/upb/.yandex_meta/licenses.list.txt337
-rw-r--r--contrib/libs/grpc/third_party/upb/CMakeLists.txt9
-rw-r--r--contrib/libs/grpc/third_party/upb/third_party/wyhash/LICENSE25
-rw-r--r--contrib/libs/grpc/third_party/upb/third_party/wyhash/wyhash.h145
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode.c415
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode.h21
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode.int.h163
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode_fast.c1040
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/decode_fast.h126
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.c2178
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.h315
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/def.hpp439
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/encode.c396
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/encode.h29
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/msg.c255
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/msg.h208
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/port.c26
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/port_def.inc135
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/port_undef.inc10
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/reflection.c408
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/reflection.h168
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/table.c231
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/table.int.h19
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/text_encode.c421
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/text_encode.h38
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.c59
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.h43
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.hpp8
-rw-r--r--contrib/libs/grpc/third_party/upb/upb/upb.int.h29
32 files changed, 6927 insertions, 811 deletions
diff --git a/contrib/libs/grpc/third_party/ABSEIL_MANUAL.md b/contrib/libs/grpc/third_party/ABSEIL_MANUAL.md
new file mode 100644
index 0000000000..0fd4181199
--- /dev/null
+++ b/contrib/libs/grpc/third_party/ABSEIL_MANUAL.md
@@ -0,0 +1,32 @@
+# Abseil in gRPC
+
+This document explains how to use Abseil throughout gRPC. Note that this isn't
+supposed to explain general usage of Abseil.
+
+## The version of Abseil
+
+gRPC intends to use the LTS versions of Abseil only because it simplifies
+dependency management. Abseil is being distributed via package distribution
+systems such as vcpkg and cocoapods. If gRPC depends on the certain version
+that aren't registered, gRPC in that system cannot get the right version of
+Abseil when being built, resulting in a build failure.
+Therefore, gRPC will use the LTS version only, preferably the latest one.
+
+## Libraries that are not ready to use
+
+Most of Abseil libraries are okay to use but there are some exceptions
+because they're not going well yet on some of our test machinaries or
+platforms it supports. The following is a list of targets that are NOT
+ready to use.
+
+- `y_absl/synchronization:*`: This will be ready from the LTS version in 2021.
+- `y_absl/random`: [WIP](https://github.com/grpc/grpc/pull/23346).
+- `y_absl/types:variant`: [WIP](https://github.com/grpc/grpc/pull/22961).
+
+## Implemetation only
+
+You can use Abseil in gRPC Core and gRPC C++. But you cannot use it in
+the public interface of gRPC C++ because i) it doesn't gurantee no breaking
+API changes like gRPC C++ does and ii) it may make users change their build
+system to address Abseil.
+ \ No newline at end of file
diff --git a/contrib/libs/grpc/third_party/README.md b/contrib/libs/grpc/third_party/README.md
index 9bf04831bc..473b542644 100644
--- a/contrib/libs/grpc/third_party/README.md
+++ b/contrib/libs/grpc/third_party/README.md
@@ -48,6 +48,14 @@ Usually the process is
Updating some dependencies requires extra care.
+### Updating third_party/abseil-cpp
+
+- Two additional steps should be done before running `generate_projects.sh` above.
+ - Running `src/abseil-cpp/preprocessed_builds.yaml.gen.py`.
+ - Updating `abseil_version =` scripts in `templates/gRPC-C++.podspec.template` and
+ `templates/gRPC-Core.podspec.template`.
+- You can see an example of previous [upgrade](https://github.com/grpc/grpc/pull/24270).
+
### Updating third_party/boringssl-with-bazel
- Update the `third_party/boringssl-with-bazel` submodule to the latest [`master-with-bazel`](https://github.com/google/boringssl/tree/master-with-bazel) branch
diff --git a/contrib/libs/grpc/third_party/address_sorting/include/address_sorting/address_sorting.h b/contrib/libs/grpc/third_party/address_sorting/include/address_sorting/address_sorting.h
index c58fafe3f7..074fc7554e 100644
--- a/contrib/libs/grpc/third_party/address_sorting/include/address_sorting/address_sorting.h
+++ b/contrib/libs/grpc/third_party/address_sorting/include/address_sorting/address_sorting.h
@@ -41,6 +41,8 @@
#ifndef ADDRESS_SORTING_H
#define ADDRESS_SORTING_H
+#include <stddef.h>
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/contrib/libs/grpc/third_party/upb/.yandex_meta/licenses.list.txt b/contrib/libs/grpc/third_party/upb/.yandex_meta/licenses.list.txt
index b1f339a11d..fb787bff11 100644
--- a/contrib/libs/grpc/third_party/upb/.yandex_meta/licenses.list.txt
+++ b/contrib/libs/grpc/third_party/upb/.yandex_meta/licenses.list.txt
@@ -23,9 +23,344 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
====================COPYRIGHT====================
+/* Copyright 2020 王一 Wang Yi <godspeed_china@yeah.net>
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
+ See github.com/wangyi-fudan/wyhash/ LICENSE
+
+
+====================COPYRIGHT====================
Copyright (c) 2009-2011, Google Inc.
All rights reserved.
+====================File: AUTHORS====================
+Dropbox, Inc.
+Google Inc.
+Skyscanner Ltd.
+WeWork Companies Inc.
+
+
+====================File: LICENSE====================
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+====================File: third_party/address_sorting/LICENSE====================
+Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. 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.
+3. Neither the name of the project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+
+====================File: third_party/upb/LICENSE====================
+
+Copyright (c) 2009-2011, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Google Inc. nor the names of any other
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``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 INC. 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.
+
+
+====================File: third_party/upb/third_party/wyhash/LICENSE====================
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
+
+
+
====================Public-Domain====================
- * MurmurHash2, by Austin Appleby (released as public domain).
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
+
+
+====================Unlicense====================
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
+
+
+====================Unlicense====================
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/contrib/libs/grpc/third_party/upb/CMakeLists.txt b/contrib/libs/grpc/third_party/upb/CMakeLists.txt
index d3c68ad50f..e038006314 100644
--- a/contrib/libs/grpc/third_party/upb/CMakeLists.txt
+++ b/contrib/libs/grpc/third_party/upb/CMakeLists.txt
@@ -14,13 +14,20 @@ target_compile_options(grpc-third_party-upb PRIVATE
target_include_directories(grpc-third_party-upb PRIVATE
${CMAKE_BINARY_DIR}/contrib/libs/grpc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb
)
target_sources(grpc-third_party-upb PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/protobuf/descriptor.upbdefs.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/msg.c
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/port.c
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/third_party/upb/upb/reflection.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/third_party/wyhash/LICENSE b/contrib/libs/grpc/third_party/upb/third_party/wyhash/LICENSE
new file mode 100644
index 0000000000..471f09f4cf
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/third_party/wyhash/LICENSE
@@ -0,0 +1,25 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
+
diff --git a/contrib/libs/grpc/third_party/upb/third_party/wyhash/wyhash.h b/contrib/libs/grpc/third_party/upb/third_party/wyhash/wyhash.h
new file mode 100644
index 0000000000..5658f02df3
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/third_party/wyhash/wyhash.h
@@ -0,0 +1,145 @@
+/* Copyright 2020 王一 Wang Yi <godspeed_china@yeah.net>
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
+ See github.com/wangyi-fudan/wyhash/ LICENSE
+ */
+#ifndef wyhash_final_version
+#define wyhash_final_version
+//defines that change behavior
+#ifndef WYHASH_CONDOM
+#define WYHASH_CONDOM 1 //0: read 8 bytes before and after boundaries, dangerous but fastest. 1: normal valid behavior 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication"
+#endif
+#define WYHASH_32BIT_MUM 0 //faster on 32 bit system
+//includes
+#include <stdint.h>
+#include <string.h>
+#if defined(_MSC_VER) && defined(_M_X64)
+ #include <intrin.h>
+ #pragma intrinsic(_umul128)
+#endif
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+ #define _likely_(x) __builtin_expect(x,1)
+ #define _unlikely_(x) __builtin_expect(x,0)
+#else
+ #define _likely_(x) (x)
+ #define _unlikely_(x) (x)
+#endif
+//mum function
+static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); }
+static inline void _wymum(uint64_t *A, uint64_t *B){
+#if(WYHASH_32BIT_MUM)
+ uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B;
+ #if(WYHASH_CONDOM>1)
+ *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll;
+ #else
+ *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll;
+ #endif
+#elif defined(__SIZEOF_INT128__)
+ __uint128_t r=*A; r*=*B;
+ #if(WYHASH_CONDOM>1)
+ *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
+ #else
+ *A=(uint64_t)r; *B=(uint64_t)(r>>64);
+ #endif
+#elif defined(_MSC_VER) && defined(_M_X64)
+ #if(WYHASH_CONDOM>1)
+ uint64_t a, b;
+ a=_umul128(*A,*B,&b);
+ *A^=a; *B^=b;
+ #else
+ *A=_umul128(*A,*B,B);
+ #endif
+#else
+ uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
+ uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
+ lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
+ #if(WYHASH_CONDOM>1)
+ *A^=lo; *B^=hi;
+ #else
+ *A=lo; *B=hi;
+ #endif
+#endif
+}
+static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; }
+//read functions
+#ifndef WYHASH_LITTLE_ENDIAN
+ #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ #define WYHASH_LITTLE_ENDIAN 1
+ #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ #define WYHASH_LITTLE_ENDIAN 0
+ #endif
+#endif
+#if (WYHASH_LITTLE_ENDIAN)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;}
+#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);}
+#elif defined(_MSC_VER)
+static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);}
+static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);}
+#endif
+static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
+//wyhash function
+static inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
+#if(WYHASH_CONDOM>0)
+ uint64_t a, b;
+ if(_likely_(i<=8)){
+ if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4); }
+ else if (_likely_(i)){ a=_wyr3(p,i); b=0; }
+ else a=b=0;
+ }
+ else{ a=_wyr8(p); b=_wyr8(p+i-8); }
+ return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed));
+#else
+ #define oneshot_shift ((i<8)*((8-i)<<3))
+ return _wymix(secret[1]^len,_wymix((_wyr8(p)<<oneshot_shift)^secret[1],(_wyr8(p+i-8)>>oneshot_shift)^seed));
+#endif
+}
+
+static inline uint64_t _wyfinish(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
+ if(_likely_(i<=16)) return _wyfinish16(p,len,seed,secret,i);
+ return _wyfinish(p+16,len,_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed),secret,i-16);
+}
+
+static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){
+ const uint8_t *p=(const uint8_t *)key;
+ uint64_t i=len; seed^=*secret;
+ if(_unlikely_(i>64)){
+ uint64_t see1=seed;
+ do{
+ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed)^_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^seed);
+ see1=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see1)^_wymix(_wyr8(p+48)^secret[4],_wyr8(p+56)^see1);
+ p+=64; i-=64;
+ }while(i>64);
+ seed^=see1;
+ }
+ return _wyfinish(p,len,seed,secret,i);
+}
+//utility functions
+const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
+static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=_wyp[0]; B^=_wyp[1]; _wymum(&A,&B); return _wymix(A^_wyp[0],B^_wyp[1]);}
+static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);}
+static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}
+static inline double wy2gau(uint64_t r){ const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;}
+static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; }
+
+static inline void make_secret(uint64_t seed, uint64_t *secret){
+ uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 204, 209, 210, 212, 216, 225, 226, 228, 232, 240 };
+ for(size_t i=0;i<5;i++){
+ uint8_t ok;
+ do{
+ ok=1; secret[i]=0;
+ for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<<j;
+ if(secret[i]%2==0){ ok=0; continue; }
+ for(size_t j=0;j<i;j++)
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
+ if(__builtin_popcountll(secret[j]^secret[i])!=32){ ok=0; break; }
+#elif defined(_MSC_VER) && defined(_M_X64)
+ if(_mm_popcnt_u64(secret[j]^secret[i])!=32){ ok=0; break; }
+#endif
+ if(!ok)continue;
+ for(uint64_t j=3;j<0x100000000ull;j+=2) if(secret[i]%j==0){ ok=0; break; }
+ }while(!ok);
+ }
+}
+#endif
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode.c b/contrib/libs/grpc/third_party/upb/upb/decode.c
index a9f1cf548a..a5f0666fa8 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode.c
+++ b/contrib/libs/grpc/third_party/upb/upb/decode.c
@@ -1,33 +1,37 @@
+#include "upb/decode.h"
+
#include <setjmp.h>
#include <string.h>
-#include "upb/decode.h"
+#include "upb/decode.int.h"
#include "upb/upb.h"
+#include "upb/upb.int.h"
+/* Must be last. */
#include "upb/port_def.inc"
-/* Maps descriptor type -> upb field type. */
-static const uint8_t desctype_to_fieldtype[] = {
+/* Maps descriptor type -> elem_size_lg2. */
+static const uint8_t desctype_to_elem_size_lg2[] = {
-1, /* invalid descriptor type */
- UPB_TYPE_DOUBLE, /* DOUBLE */
- UPB_TYPE_FLOAT, /* FLOAT */
- UPB_TYPE_INT64, /* INT64 */
- UPB_TYPE_UINT64, /* UINT64 */
- UPB_TYPE_INT32, /* INT32 */
- UPB_TYPE_UINT64, /* FIXED64 */
- UPB_TYPE_UINT32, /* FIXED32 */
- UPB_TYPE_BOOL, /* BOOL */
- UPB_TYPE_STRING, /* STRING */
- UPB_TYPE_MESSAGE, /* GROUP */
- UPB_TYPE_MESSAGE, /* MESSAGE */
- UPB_TYPE_BYTES, /* BYTES */
- UPB_TYPE_UINT32, /* UINT32 */
- UPB_TYPE_ENUM, /* ENUM */
- UPB_TYPE_INT32, /* SFIXED32 */
- UPB_TYPE_INT64, /* SFIXED64 */
- UPB_TYPE_INT32, /* SINT32 */
- UPB_TYPE_INT64, /* SINT64 */
+ 3, /* DOUBLE */
+ 2, /* FLOAT */
+ 3, /* INT64 */
+ 3, /* UINT64 */
+ 2, /* INT32 */
+ 3, /* FIXED64 */
+ 2, /* FIXED32 */
+ 0, /* BOOL */
+ UPB_SIZE(3, 4), /* STRING */
+ UPB_SIZE(2, 3), /* GROUP */
+ UPB_SIZE(2, 3), /* MESSAGE */
+ UPB_SIZE(3, 4), /* BYTES */
+ 2, /* UINT32 */
+ 2, /* ENUM */
+ 2, /* SFIXED32 */
+ 3, /* SFIXED64 */
+ 2, /* SINT32 */
+ 3, /* SINT64 */
};
/* Maps descriptor type -> upb map size. */
@@ -134,106 +138,101 @@ static const int8_t delim_ops[37] = {
OP_VARPCK_LG2(3), /* REPEATED SINT64 */
};
-/* Data pertaining to the parse. */
-typedef struct {
- const char *limit; /* End of delimited region or end of buffer. */
- upb_arena *arena;
- int depth;
- uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */
- jmp_buf err;
-} upb_decstate;
-
typedef union {
bool bool_val;
uint32_t uint32_val;
uint64_t uint64_val;
- upb_strview str_val;
+ uint32_t size;
} wireval;
static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout);
-UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); }
-
-void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
- static const uint8_t utf8_offset[] = {
- 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
- };
-
- int i, j;
- uint8_t offset;
-
- i = 0;
- while (i < len) {
- offset = utf8_offset[(uint8_t)buf[i]];
- if (offset == 0 || i + offset > len) {
- decode_err(d);
- }
- for (j = i + 1; j < i + offset; j++) {
- if ((buf[j] & 0xc0) != 0x80) {
- decode_err(d);
- }
- }
- i += offset;
- }
- if (i != len) decode_err(d);
+UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); }
+
+const char *fastdecode_err(upb_decstate *d) {
+ longjmp(d->err, 1);
+ return NULL;
+}
+
+const uint8_t upb_utf8_offsets[] = {
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
+ if (!decode_verifyutf8_inl(buf, len)) decode_err(d);
}
static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
bool need_realloc = arr->size - arr->len < elem;
- if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) {
+ if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) {
decode_err(d);
}
return need_realloc;
}
+typedef struct {
+ const char *ptr;
+ uint64_t val;
+} decode_vret;
+
UPB_NOINLINE
-static const char *decode_longvarint64(upb_decstate *d, const char *ptr,
- const char *limit, uint64_t *val) {
- uint8_t byte;
- int bitpos = 0;
- uint64_t out = 0;
-
- do {
- if (bitpos >= 70 || ptr == limit) decode_err(d);
- byte = *ptr;
- out |= (uint64_t)(byte & 0x7F) << bitpos;
- ptr++;
- bitpos += 7;
- } while (byte & 0x80);
-
- *val = out;
- return ptr;
+static decode_vret decode_longvarint64(const char *ptr, uint64_t val) {
+ decode_vret ret = {NULL, 0};
+ uint64_t byte;
+ int i;
+ for (i = 1; i < 10; i++) {
+ byte = (uint8_t)ptr[i];
+ val += (byte - 1) << (i * 7);
+ if (!(byte & 0x80)) {
+ ret.ptr = ptr + i + 1;
+ ret.val = val;
+ return ret;
+ }
+ }
+ return ret;
}
UPB_FORCEINLINE
static const char *decode_varint64(upb_decstate *d, const char *ptr,
- const char *limit, uint64_t *val) {
- if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) {
- *val = (uint8_t)*ptr;
+ uint64_t *val) {
+ uint64_t byte = (uint8_t)*ptr;
+ if (UPB_LIKELY((byte & 0x80) == 0)) {
+ *val = byte;
return ptr + 1;
} else {
- return decode_longvarint64(d, ptr, limit, val);
+ decode_vret res = decode_longvarint64(ptr, byte);
+ if (!res.ptr) decode_err(d);
+ *val = res.val;
+ return res.ptr;
}
}
-static const char *decode_varint32(upb_decstate *d, const char *ptr,
- const char *limit, uint32_t *val) {
- uint64_t u64;
- ptr = decode_varint64(d, ptr, limit, &u64);
- if (u64 > UINT32_MAX) decode_err(d);
- *val = (uint32_t)u64;
- return ptr;
+UPB_FORCEINLINE
+static const char *decode_tag(upb_decstate *d, const char *ptr,
+ uint32_t *val) {
+ uint64_t byte = (uint8_t)*ptr;
+ if (UPB_LIKELY((byte & 0x80) == 0)) {
+ *val = byte;
+ return ptr + 1;
+ } else {
+ const char *start = ptr;
+ decode_vret res = decode_longvarint64(ptr, byte);
+ ptr = res.ptr;
+ *val = res.val;
+ if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d);
+ return ptr;
+ }
}
static void decode_munge(int type, wireval *val) {
@@ -280,33 +279,65 @@ static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
const upb_msglayout_field *field) {
const upb_msglayout *subl = layout->submsgs[field->submsg_index];
- return _upb_msg_new(subl, d->arena);
+ return _upb_msg_new_inl(subl, &d->arena);
+}
+
+UPB_NOINLINE
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+ int overrun) {
+ ptr = decode_isdonefallback_inl(d, ptr, overrun);
+ if (ptr == NULL) {
+ decode_err(d);
+ }
+ return ptr;
+}
+
+static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
+ upb_strview *str) {
+ if (d->alias) {
+ str->data = ptr;
+ } else {
+ char *data = upb_arena_malloc(&d->arena, size);
+ if (!data) decode_err(d);
+ memcpy(data, ptr, size);
+ str->data = data;
+ }
+ str->size = size;
+ return ptr + size;
}
-static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
- const upb_msglayout *layout,
- const upb_msglayout_field *field, upb_strview val) {
+UPB_FORCEINLINE
+static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
+ upb_msg *submsg, const upb_msglayout *layout,
+ const upb_msglayout_field *field, int size) {
const upb_msglayout *subl = layout->submsgs[field->submsg_index];
- const char *saved_limit = d->limit;
+ int saved_delta = decode_pushlimit(d, ptr, size);
if (--d->depth < 0) decode_err(d);
- d->limit = val.data + val.size;
- decode_msg(d, val.data, submsg, subl);
- d->limit = saved_limit;
- if (d->end_group != 0) decode_err(d);
+ if (!decode_isdone(d, &ptr)) {
+ ptr = decode_msg(d, ptr, submsg, subl);
+ }
+ if (d->end_group != DECODE_NOGROUP) decode_err(d);
+ decode_poplimit(d, ptr, saved_delta);
d->depth++;
+ return ptr;
}
+UPB_FORCEINLINE
static const char *decode_group(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *subl,
uint32_t number) {
if (--d->depth < 0) decode_err(d);
+ if (decode_isdone(d, &ptr)) {
+ decode_err(d);
+ }
ptr = decode_msg(d, ptr, submsg, subl);
if (d->end_group != number) decode_err(d);
- d->end_group = 0;
+ d->end_group = DECODE_NOGROUP;
d->depth++;
return ptr;
}
+UPB_FORCEINLINE
static const char *decode_togroup(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *layout,
const upb_msglayout_field *field) {
@@ -322,15 +353,15 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
upb_array *arr = *arrp;
void *mem;
- if (!arr) {
- upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype];
- arr = _upb_array_new(d->arena, type);
+ if (arr) {
+ decode_reserve(d, arr, 1);
+ } else {
+ size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype];
+ arr = _upb_array_new(&d->arena, 4, lg2);
if (!arr) decode_err(d);
*arrp = arr;
}
- decode_reserve(d, arr, 1);
-
switch (op) {
case OP_SCALAR_LG2(0):
case OP_SCALAR_LG2(2):
@@ -341,15 +372,14 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
memcpy(mem, &val, 1 << op);
return ptr;
case OP_STRING:
- decode_verifyutf8(d, val.str_val.data, val.str_val.size);
+ decode_verifyutf8(d, ptr, val.size);
/* Fallthrough. */
- case OP_BYTES:
+ case OP_BYTES: {
/* Append bytes. */
- mem =
- UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void);
+ upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
arr->len++;
- memcpy(mem, &val, sizeof(upb_strview));
- return ptr;
+ return decode_readstr(d, ptr, val.size, str);
+ }
case OP_SUBMSG: {
/* Append submessage / group. */
upb_msg *submsg = decode_newsubmsg(d, layout, field);
@@ -357,26 +387,25 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
submsg;
arr->len++;
if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
- ptr = decode_togroup(d, ptr, submsg, layout, field);
+ return decode_togroup(d, ptr, submsg, layout, field);
} else {
- decode_tosubmsg(d, submsg, layout, field, val.str_val);
+ return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
}
- return ptr;
}
case OP_FIXPCK_LG2(2):
case OP_FIXPCK_LG2(3): {
/* Fixed packed. */
int lg2 = op - OP_FIXPCK_LG2(0);
int mask = (1 << lg2) - 1;
- size_t count = val.str_val.size >> lg2;
- if ((val.str_val.size & mask) != 0) {
+ size_t count = val.size >> lg2;
+ if ((val.size & mask) != 0) {
decode_err(d); /* Length isn't a round multiple of elem size. */
}
decode_reserve(d, arr, count);
mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
arr->len += count;
- memcpy(mem, val.str_val.data, val.str_val.size);
- return ptr;
+ memcpy(mem, ptr, val.size); /* XXX: ptr boundary. */
+ return ptr + val.size;
}
case OP_VARPCK_LG2(0):
case OP_VARPCK_LG2(2):
@@ -384,12 +413,11 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
/* Varint packed. */
int lg2 = op - OP_VARPCK_LG2(0);
int scale = 1 << lg2;
- const char *ptr = val.str_val.data;
- const char *end = ptr + val.str_val.size;
+ int saved_limit = decode_pushlimit(d, ptr, val.size);
char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
- while (ptr < end) {
+ while (!decode_isdone(d, &ptr)) {
wireval elem;
- ptr = decode_varint64(d, ptr, end, &elem.uint64_val);
+ ptr = decode_varint64(d, ptr, &elem.uint64_val);
decode_munge(field->descriptortype, &elem);
if (decode_reserve(d, arr, 1)) {
out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
@@ -398,7 +426,7 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
memcpy(out, &elem, scale);
out += scale;
}
- if (ptr != end) decode_err(d);
+ decode_poplimit(d, ptr, saved_limit);
return ptr;
}
default:
@@ -406,9 +434,9 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
}
}
-static void decode_tomap(upb_decstate *d, upb_msg *msg,
- const upb_msglayout *layout,
- const upb_msglayout_field *field, wireval val) {
+static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
+ const upb_msglayout *layout,
+ const upb_msglayout_field *field, wireval val) {
upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
upb_map *map = *map_p;
upb_map_entry ent;
@@ -423,7 +451,7 @@ static void decode_tomap(upb_decstate *d, upb_msg *msg,
char val_size = desctype_to_mapsize[val_field->descriptortype];
UPB_ASSERT(key_field->offset == 0);
UPB_ASSERT(val_field->offset == sizeof(upb_strview));
- map = _upb_map_new(d->arena, key_size, val_size);
+ map = _upb_map_new(&d->arena, key_size, val_size);
*map_p = map;
}
@@ -433,13 +461,12 @@ static void decode_tomap(upb_decstate *d, upb_msg *msg,
if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
/* Create proactively to handle the case where it doesn't appear. */
- ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], d->arena));
+ ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
}
- decode_tosubmsg(d, &ent.k, layout, field, val.str_val);
-
- /* Insert into map. */
- _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
+ ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
+ _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
+ return ptr;
}
static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
@@ -473,16 +500,15 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
ptr = decode_togroup(d, ptr, submsg, layout, field);
} else {
- decode_tosubmsg(d, submsg, layout, field, val.str_val);
+ ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
}
break;
}
case OP_STRING:
- decode_verifyutf8(d, val.str_val.data, val.str_val.size);
+ decode_verifyutf8(d, ptr, val.size);
/* Fallthrough. */
case OP_BYTES:
- memcpy(mem, &val, sizeof(upb_strview));
- break;
+ return decode_readstr(d, ptr, val.size, mem);
case OP_SCALAR_LG2(3):
memcpy(mem, &val, 8);
break;
@@ -499,9 +525,24 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
return ptr;
}
+UPB_FORCEINLINE
+static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
+ upb_msg *msg, const upb_msglayout *layout) {
+#if UPB_FASTTABLE
+ if (layout && layout->table_mask != (unsigned char)-1) {
+ uint16_t tag = fastdecode_loadtag(*ptr);
+ intptr_t table = decode_totable(layout);
+ *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag);
+ return true;
+ }
+#endif
+ return false;
+}
+
+UPB_NOINLINE
static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout) {
- while (ptr < d->limit) {
+ while (true) {
uint32_t tag;
const upb_msglayout_field *field;
int field_number;
@@ -510,7 +551,8 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
wireval val;
int op;
- ptr = decode_varint32(d, ptr, d->limit, &tag);
+ UPB_ASSERT(ptr < d->limit_ptr);
+ ptr = decode_tag(d, ptr, &tag);
field_number = tag >> 3;
wire_type = tag & 7;
@@ -518,12 +560,11 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
switch (wire_type) {
case UPB_WIRE_TYPE_VARINT:
- ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val);
+ ptr = decode_varint64(d, ptr, &val.uint64_val);
op = varint_ops[field->descriptortype];
decode_munge(field->descriptortype, &val);
break;
case UPB_WIRE_TYPE_32BIT:
- if (d->limit - ptr < 4) decode_err(d);
memcpy(&val.uint32_val, ptr, 4);
val.uint32_val = _upb_be_swap32(val.uint32_val);
ptr += 4;
@@ -531,7 +572,6 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
break;
case UPB_WIRE_TYPE_64BIT:
- if (d->limit - ptr < 8) decode_err(d);
memcpy(&val.uint64_val, ptr, 8);
val.uint64_val = _upb_be_swap64(val.uint64_val);
ptr += 8;
@@ -539,17 +579,16 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
break;
case UPB_WIRE_TYPE_DELIMITED: {
- uint32_t size;
int ndx = field->descriptortype;
+ uint64_t size;
if (_upb_isrepeated(field)) ndx += 18;
- ptr = decode_varint32(d, ptr, d->limit, &size);
- if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) {
+ ptr = decode_varint64(d, ptr, &size);
+ if (size >= INT32_MAX ||
+ ptr - d->end + (int32_t)size > d->limit) {
decode_err(d); /* Length overflow. */
}
- val.str_val.data = ptr;
- val.str_val.size = size;
- ptr += size;
op = delim_ops[ndx];
+ val.size = size;
break;
}
case UPB_WIRE_TYPE_START_GROUP:
@@ -572,7 +611,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
break;
case _UPB_LABEL_MAP:
- decode_tomap(d, msg, layout, field, val);
+ ptr = decode_tomap(d, ptr, msg, layout, field, val);
break;
default:
ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
@@ -582,36 +621,78 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
unknown:
/* Skip unknown field. */
if (field_number == 0) decode_err(d);
- if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
- ptr = decode_group(d, ptr, NULL, NULL, field_number);
- }
+ if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
if (msg) {
+ if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+ d->unknown = field_start;
+ d->unknown_msg = msg;
+ ptr = decode_group(d, ptr, NULL, NULL, field_number);
+ d->unknown_msg = NULL;
+ field_start = d->unknown;
+ }
if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
- d->arena)) {
+ &d->arena)) {
decode_err(d);
}
+ } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+ ptr = decode_group(d, ptr, NULL, NULL, field_number);
}
}
+
+ if (decode_isdone(d, &ptr)) return ptr;
+ if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr;
}
+}
- if (ptr != d->limit) decode_err(d);
- return ptr;
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table, uint64_t hasbits,
+ uint64_t data) {
+ (void)data;
+ *(uint32_t*)msg |= hasbits;
+ return decode_msg(d, ptr, msg, decode_totablep(table));
}
-bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
- upb_arena *arena) {
+bool _upb_decode(const char *buf, size_t size, void *msg,
+ const upb_msglayout *l, upb_arena *arena, int options) {
+ bool ok;
upb_decstate state;
- state.limit = buf + size;
- state.arena = arena;
- state.depth = 64;
- state.end_group = 0;
+ unsigned depth = (unsigned)options >> 16;
+
+ if (size == 0) {
+ return true;
+ } else if (size <= 16) {
+ memset(&state.patch, 0, 32);
+ memcpy(&state.patch, buf, size);
+ buf = state.patch;
+ state.end = buf + size;
+ state.limit = 0;
+ state.alias = false;
+ } else {
+ state.end = buf + size - 16;
+ state.limit = 16;
+ state.alias = options & UPB_DECODE_ALIAS;
+ }
- if (setjmp(state.err)) return false;
+ state.limit_ptr = state.end;
+ state.unknown_msg = NULL;
+ state.depth = depth ? depth : 64;
+ state.end_group = DECODE_NOGROUP;
+ state.arena.head = arena->head;
+ state.arena.last_size = arena->last_size;
+ state.arena.parent = arena;
- if (size == 0) return true;
- decode_msg(&state, buf, msg, l);
+ if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
+ ok = false;
+ } else {
+ if (!decode_tryfastdispatch(&state, &buf, msg, l)) {
+ decode_msg(&state, buf, msg, l);
+ }
+ ok = state.end_group == DECODE_NOGROUP;
+ }
- return state.end_group == 0;
+ arena->head.ptr = state.arena.head.ptr;
+ arena->head.end = state.arena.head.end;
+ return ok;
}
#undef OP_SCALAR_LG2
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode.h b/contrib/libs/grpc/third_party/upb/upb/decode.h
index 9de8638de5..eff4b8bd3d 100644
--- a/contrib/libs/grpc/third_party/upb/upb/decode.h
+++ b/contrib/libs/grpc/third_party/upb/upb/decode.h
@@ -7,15 +7,34 @@
#include "upb/msg.h"
+/* Must be last. */
+#include "upb/port_def.inc"
+
#ifdef __cplusplus
extern "C" {
#endif
+enum {
+ /* If set, strings will alias the input buffer instead of copying into the
+ * arena. */
+ UPB_DECODE_ALIAS = 1,
+};
+
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+
+bool _upb_decode(const char *buf, size_t size, upb_msg *msg,
+ const upb_msglayout *l, upb_arena *arena, int options);
+
+UPB_INLINE
bool upb_decode(const char *buf, size_t size, upb_msg *msg,
- const upb_msglayout *l, upb_arena *arena);
+ const upb_msglayout *l, upb_arena *arena) {
+ return _upb_decode(buf, size, msg, l, arena, 0);
+}
#ifdef __cplusplus
} /* extern "C" */
#endif
+#include "upb/port_undef.inc"
+
#endif /* UPB_DECODE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode.int.h b/contrib/libs/grpc/third_party/upb/upb/decode.int.h
new file mode 100644
index 0000000000..e286b9cdd5
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/decode.int.h
@@ -0,0 +1,163 @@
+/*
+** Internal implementation details of the decoder that are shared between
+** decode.c and decode_fast.c.
+*/
+
+#ifndef UPB_DECODE_INT_H_
+#define UPB_DECODE_INT_H_
+
+#include <setjmp.h>
+
+#include "upb/msg.h"
+#include "upb/upb.int.h"
+
+/* Must be last. */
+#include "upb/port_def.inc"
+
+#define DECODE_NOGROUP -1
+
+typedef struct upb_decstate {
+ const char *end; /* Can read up to 16 bytes slop beyond this. */
+ const char *limit_ptr; /* = end + UPB_MIN(limit, 0) */
+ upb_msg *unknown_msg; /* If non-NULL, add unknown data at buffer flip. */
+ const char *unknown; /* Start of unknown data. */
+ int limit; /* Submessage limit relative to end. */
+ int depth;
+ uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
+ bool alias;
+ char patch[32];
+ upb_arena arena;
+ jmp_buf err;
+} upb_decstate;
+
+/* Error function that will abort decoding with longjmp(). We can't declare this
+ * UPB_NORETURN, even though it is appropriate, because if we do then compilers
+ * will "helpfully" refuse to tailcall to it
+ * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal
+ * of our optimizations. That is also why we must declare it in a separate file,
+ * otherwise the compiler will see that it calls longjmp() and deduce that it is
+ * noreturn. */
+const char *fastdecode_err(upb_decstate *d);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool decode_verifyutf8_inl(const char *buf, int len) {
+ int i, j;
+ uint8_t offset;
+
+ i = 0;
+ while (i < len) {
+ offset = upb_utf8_offsets[(uint8_t)buf[i]];
+ if (offset == 0 || i + offset > len) {
+ return false;
+ }
+ for (j = i + 1; j < i + offset; j++) {
+ if ((buf[j] & 0xc0) != 0x80) {
+ return false;
+ }
+ }
+ i += offset;
+ }
+ return i == len;
+}
+
+/* x86-64 pointers always have the high 16 bits matching. So we can shift
+ * left 8 and right 8 without loss of information. */
+UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) {
+ return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) {
+ return (const upb_msglayout*)(table >> 8);
+}
+
+UPB_INLINE
+const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr,
+ int overrun) {
+ if (overrun < d->limit) {
+ /* Need to copy remaining data into patch buffer. */
+ UPB_ASSERT(overrun < 16);
+ if (d->unknown_msg) {
+ if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+ &d->arena)) {
+ return NULL;
+ }
+ d->unknown = &d->patch[0] + overrun;
+ }
+ memset(d->patch + 16, 0, 16);
+ memcpy(d->patch, d->end, 16);
+ ptr = &d->patch[0] + overrun;
+ d->end = &d->patch[16];
+ d->limit -= 16;
+ d->limit_ptr = d->end + d->limit;
+ d->alias = false;
+ UPB_ASSERT(ptr < d->limit_ptr);
+ return ptr;
+ } else {
+ return NULL;
+ }
+}
+
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+ int overrun);
+
+UPB_INLINE
+bool decode_isdone(upb_decstate *d, const char **ptr) {
+ int overrun = *ptr - d->end;
+ if (UPB_LIKELY(*ptr < d->limit_ptr)) {
+ return false;
+ } else if (UPB_LIKELY(overrun == d->limit)) {
+ return true;
+ } else {
+ *ptr = decode_isdonefallback(d, *ptr, overrun);
+ return false;
+ }
+}
+
+UPB_INLINE
+const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table,
+ uint64_t hasbits, uint32_t tag) {
+ const upb_msglayout *table_p = decode_totablep(table);
+ uint8_t mask = table;
+ uint64_t data;
+ size_t idx = tag & mask;
+ UPB_ASSUME((idx & 7) == 0);
+ idx >>= 3;
+ data = table_p->fasttable[idx].field_data ^ tag;
+ return table_p->fasttable[idx].field_parser(d, ptr, msg, table, hasbits, data);
+}
+
+UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) {
+ uint16_t tag;
+ memcpy(&tag, ptr, 2);
+ return tag;
+}
+
+UPB_INLINE void decode_checklimit(upb_decstate *d) {
+ UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) {
+ int limit = size + (int)(ptr - d->end);
+ int delta = d->limit - limit;
+ decode_checklimit(d);
+ d->limit = limit;
+ d->limit_ptr = d->end + UPB_MIN(0, limit);
+ decode_checklimit(d);
+ return delta;
+}
+
+UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr,
+ int saved_delta) {
+ UPB_ASSERT(ptr - d->end == d->limit);
+ decode_checklimit(d);
+ d->limit += saved_delta;
+ d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+ decode_checklimit(d);
+}
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_DECODE_INT_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode_fast.c b/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
new file mode 100644
index 0000000000..f628e6dbd4
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/decode_fast.c
@@ -0,0 +1,1040 @@
+// Fast decoder: ~3x the speed of decode.c, but x86-64 specific.
+// Also the table size grows by 2x.
+//
+// Could potentially be ported to ARM64 or other 64-bit archs that pass at
+// least six arguments in registers.
+//
+// The overall design is to create specialized functions for every possible
+// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
+// to the specialized function as quickly as possible.
+
+#include "upb/decode_fast.h"
+
+#include "upb/decode.int.h"
+
+/* Must be last. */
+#include "upb/port_def.inc"
+
+#if UPB_FASTTABLE
+
+// The standard set of arguments passed to each parsing function.
+// Thanks to x86-64 calling conventions, these will stay in registers.
+#define UPB_PARSE_PARAMS \
+ upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+ uint64_t hasbits, uint64_t data
+
+#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
+
+#define RETURN_GENERIC(m) \
+ /* fprintf(stderr, m); */ \
+ return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
+
+typedef enum {
+ CARD_s = 0, /* Singular (optional, non-repeated) */
+ CARD_o = 1, /* Oneof */
+ CARD_r = 2, /* Repeated */
+ CARD_p = 3 /* Packed Repeated */
+} upb_card;
+
+UPB_NOINLINE
+static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table,
+ uint64_t hasbits, int overrun) {
+ ptr = decode_isdonefallback_inl(d, ptr, overrun);
+ if (ptr == NULL) {
+ return fastdecode_err(d);
+ }
+ uint16_t tag = fastdecode_loadtag(ptr);
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table,
+ uint64_t hasbits) {
+ if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
+ int overrun = ptr - d->end;
+ if (UPB_LIKELY(overrun == d->limit)) {
+ // Parse is finished.
+ *(uint32_t*)msg |= hasbits; // Sync hasbits.
+ return ptr;
+ } else {
+ return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun);
+ }
+ }
+
+ // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
+ uint16_t tag = fastdecode_loadtag(ptr);
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_checktag(uint64_t data, int tagbytes) {
+ if (tagbytes == 1) {
+ return (data & 0xff) == 0;
+ } else {
+ return (data & 0xffff) == 0;
+ }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longsize(const char *ptr, int *size) {
+ int i;
+ UPB_ASSERT(*size & 0x80);
+ *size &= 0xff;
+ for (i = 0; i < 3; i++) {
+ ptr++;
+ size_t byte = (uint8_t)ptr[-1];
+ *size += (byte - 1) << (7 + 7 * i);
+ if (UPB_LIKELY((byte & 0x80) == 0)) return ptr;
+ }
+ ptr++;
+ size_t byte = (uint8_t)ptr[-1];
+ // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected
+ // for a 32 bit varint.
+ if (UPB_UNLIKELY(byte >= 8)) return NULL;
+ *size += (byte - 1) << 28;
+ return ptr;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck(const char *ptr, size_t len,
+ const char *end) {
+ uintptr_t uptr = (uintptr_t)ptr;
+ uintptr_t uend = (uintptr_t)end + 16;
+ uintptr_t res = uptr + len;
+ return res < uptr || res > uend;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck2(const char *ptr, size_t len,
+ const char *end) {
+ // This is one extra branch compared to the more normal:
+ // return (size_t)(end - ptr) < size;
+ // However it is one less computation if we are just about to use "ptr + len":
+ // https://godbolt.org/z/35YGPz
+ // In microbenchmarks this shows an overall 4% improvement.
+ uintptr_t uptr = (uintptr_t)ptr;
+ uintptr_t uend = (uintptr_t)end;
+ uintptr_t res = uptr + len;
+ return res < uptr || res > uend;
+}
+
+typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr,
+ void *ctx);
+
+UPB_FORCEINLINE
+static const char *fastdecode_delimited(upb_decstate *d, const char *ptr,
+ fastdecode_delimfunc *func, void *ctx) {
+ ptr++;
+ int len = (int8_t)ptr[-1];
+ if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) {
+ // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer.
+ // If it exceeds the buffer limit, limit/limit_ptr will change during
+ // sub-message parsing, so we need to preserve delta, not limit.
+ if (UPB_UNLIKELY(len & 0x80)) {
+ // Size varint >1 byte (length >= 128).
+ ptr = fastdecode_longsize(ptr, &len);
+ if (!ptr) {
+ // Corrupt wire format: size exceeded INT_MAX.
+ return NULL;
+ }
+ }
+ if (ptr - d->end + (int)len > d->limit) {
+ // Corrupt wire format: invalid limit.
+ return NULL;
+ }
+ int delta = decode_pushlimit(d, ptr, len);
+ ptr = func(d, ptr, ctx);
+ decode_poplimit(d, ptr, delta);
+ } else {
+ // Fast case: Sub-message is <128 bytes and fits in the current buffer.
+ // This means we can preserve limit/limit_ptr verbatim.
+ const char *saved_limit_ptr = d->limit_ptr;
+ int saved_limit = d->limit;
+ d->limit_ptr = ptr + len;
+ d->limit = d->limit_ptr - d->end;
+ UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+ ptr = func(d, ptr, ctx);
+ d->limit_ptr = saved_limit_ptr;
+ d->limit = saved_limit;
+ UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+ }
+ return ptr;
+}
+
+/* singular, oneof, repeated field handling ***********************************/
+
+typedef struct {
+ upb_array *arr;
+ void *end;
+} fastdecode_arr;
+
+typedef enum {
+ FD_NEXT_ATLIMIT,
+ FD_NEXT_SAMEFIELD,
+ FD_NEXT_OTHERFIELD
+} fastdecode_next;
+
+typedef struct {
+ void *dst;
+ fastdecode_next next;
+ uint32_t tag;
+} fastdecode_nextret;
+
+UPB_FORCEINLINE
+static void *fastdecode_resizearr(upb_decstate *d, void *dst,
+ fastdecode_arr *farr, int valbytes) {
+ if (UPB_UNLIKELY(dst == farr->end)) {
+ size_t old_size = farr->arr->size;
+ size_t old_bytes = old_size * valbytes;
+ size_t new_size = old_size * 2;
+ size_t new_bytes = new_size * valbytes;
+ char *old_ptr = _upb_array_ptr(farr->arr);
+ char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes);
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+ farr->arr->size = new_size;
+ farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2);
+ dst = (void*)(new_ptr + (old_size * valbytes));
+ farr->end = (void*)(new_ptr + (new_size * valbytes));
+ }
+ return dst;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) {
+ if (tagbytes == 1) {
+ return (uint8_t)tag == (uint8_t)data;
+ } else {
+ return (uint16_t)tag == (uint16_t)data;
+ }
+}
+
+UPB_FORCEINLINE
+static void fastdecode_commitarr(void *dst, fastdecode_arr *farr,
+ int valbytes) {
+ farr->arr->len =
+ (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst,
+ const char **ptr,
+ fastdecode_arr *farr,
+ uint64_t data, int tagbytes,
+ int valbytes) {
+ fastdecode_nextret ret;
+ dst = (char *)dst + valbytes;
+
+ if (UPB_LIKELY(!decode_isdone(d, ptr))) {
+ ret.tag = fastdecode_loadtag(*ptr);
+ if (fastdecode_tagmatch(ret.tag, data, tagbytes)) {
+ ret.next = FD_NEXT_SAMEFIELD;
+ } else {
+ fastdecode_commitarr(dst, farr, valbytes);
+ ret.next = FD_NEXT_OTHERFIELD;
+ }
+ } else {
+ fastdecode_commitarr(dst, farr, valbytes);
+ ret.next = FD_NEXT_ATLIMIT;
+ }
+
+ ret.dst = dst;
+ return ret;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) {
+ size_t ofs = data >> 48;
+ return (char *)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
+ uint64_t *data, uint64_t *hasbits,
+ fastdecode_arr *farr, int valbytes,
+ upb_card card) {
+ switch (card) {
+ case CARD_s: {
+ uint8_t hasbit_index = *data >> 24;
+ // Set hasbit and return pointer to scalar field.
+ *hasbits |= 1ull << hasbit_index;
+ return fastdecode_fieldmem(msg, *data);
+ }
+ case CARD_o: {
+ uint16_t case_ofs = *data >> 32;
+ uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t);
+ uint8_t field_number = *data >> 24;
+ *oneof_case = field_number;
+ return fastdecode_fieldmem(msg, *data);
+ }
+ case CARD_r: {
+ // Get pointer to upb_array and allocate/expand if necessary.
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+ upb_array **arr_p = fastdecode_fieldmem(msg, *data);
+ char *begin;
+ *(uint32_t*)msg |= *hasbits;
+ *hasbits = 0;
+ if (UPB_LIKELY(!*arr_p)) {
+ farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2);
+ *arr_p = farr->arr;
+ } else {
+ farr->arr = *arr_p;
+ }
+ begin = _upb_array_ptr(farr->arr);
+ farr->end = begin + (farr->arr->size * valbytes);
+ *data = fastdecode_loadtag(ptr);
+ return begin + (farr->arr->len * valbytes);
+ }
+ default:
+ UPB_UNREACHABLE();
+ }
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_flippacked(uint64_t *data, int tagbytes) {
+ *data ^= (0x2 ^ 0x0); // Patch data to match packed wiretype.
+ return fastdecode_checktag(*data, tagbytes);
+}
+
+/* varint fields **************************************************************/
+
+UPB_FORCEINLINE
+static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) {
+ if (valbytes == 1) {
+ return val != 0;
+ } else if (zigzag) {
+ if (valbytes == 4) {
+ uint32_t n = val;
+ return (n >> 1) ^ -(int32_t)(n & 1);
+ } else if (valbytes == 8) {
+ return (val >> 1) ^ -(int64_t)(val & 1);
+ }
+ UPB_UNREACHABLE();
+ }
+ return val;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint64(const char *ptr, uint64_t *val) {
+ ptr++;
+ *val = (uint8_t)ptr[-1];
+ if (UPB_UNLIKELY(*val & 0x80)) {
+ int i;
+ for (i = 0; i < 8; i++) {
+ ptr++;
+ uint64_t byte = (uint8_t)ptr[-1];
+ *val += (byte - 1) << (7 + 7 * i);
+ if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
+ }
+ ptr++;
+ uint64_t byte = (uint8_t)ptr[-1];
+ if (byte > 1) {
+ return NULL;
+ }
+ *val += (byte - 1) << 63;
+ }
+done:
+ UPB_ASSUME(ptr != NULL);
+ return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes, upb_card card,
+ bool zigzag,
+ _upb_field_parser *packed) {
+ uint64_t val;
+ void *dst;
+ fastdecode_arr farr;
+
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
+ return packed(UPB_PARSE_ARGS);
+ }
+ RETURN_GENERIC("varint field tag mismatch\n");
+ }
+
+ dst =
+ fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
+ if (card == CARD_r) {
+ if (UPB_UNLIKELY(!dst)) {
+ RETURN_GENERIC("need array resize\n");
+ }
+ }
+
+again:
+ if (card == CARD_r) {
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes);
+ }
+
+ ptr += tagbytes;
+ ptr = fastdecode_varint64(ptr, &val);
+ if (ptr == NULL) return fastdecode_err(d);
+ val = fastdecode_munge(val, valbytes, zigzag);
+ memcpy(dst, &val, valbytes);
+
+ if (card == CARD_r) {
+ fastdecode_nextret ret =
+ fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
+ switch (ret.next) {
+ case FD_NEXT_SAMEFIELD:
+ dst = ret.dst;
+ goto again;
+ case FD_NEXT_OTHERFIELD:
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ case FD_NEXT_ATLIMIT:
+ return ptr;
+ }
+ }
+
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+typedef struct {
+ uint8_t valbytes;
+ bool zigzag;
+ void *dst;
+ fastdecode_arr farr;
+} fastdecode_varintdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr,
+ void *ctx) {
+ fastdecode_varintdata *data = ctx;
+ void *dst = data->dst;
+ uint64_t val;
+
+ while (!decode_isdone(d, &ptr)) {
+ dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes);
+ ptr = fastdecode_varint64(ptr, &val);
+ if (ptr == NULL) return NULL;
+ val = fastdecode_munge(val, data->valbytes, data->zigzag);
+ memcpy(dst, &val, data->valbytes);
+ dst = (char *)dst + data->valbytes;
+ }
+
+ fastdecode_commitarr(dst, &data->farr, data->valbytes);
+ return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes, bool zigzag,
+ _upb_field_parser *unpacked) {
+ fastdecode_varintdata ctx = {valbytes, zigzag};
+
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ if (fastdecode_flippacked(&data, tagbytes)) {
+ return unpacked(UPB_PARSE_ARGS);
+ } else {
+ RETURN_GENERIC("varint field tag mismatch\n");
+ }
+ }
+
+ ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr,
+ valbytes, CARD_r);
+ if (UPB_UNLIKELY(!ctx.dst)) {
+ RETURN_GENERIC("need array resize\n");
+ }
+
+ ptr += tagbytes;
+ ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx);
+
+ if (UPB_UNLIKELY(ptr == NULL)) {
+ return fastdecode_err(d);
+ }
+
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes, upb_card card, bool zigzag,
+ _upb_field_parser *unpacked,
+ _upb_field_parser *packed) {
+ if (card == CARD_p) {
+ return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag,
+ unpacked);
+ } else {
+ return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card,
+ zigzag, packed);
+ }
+}
+
+#define z_ZZ true
+#define b_ZZ false
+#define v_ZZ false
+
+/* Generate all combinations:
+ * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */
+
+#define F(card, type, valbytes, tagbytes) \
+ UPB_NOINLINE \
+ const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+ return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \
+ type##_ZZ, \
+ &upb_pr##type##valbytes##_##tagbytes##bt, \
+ &upb_pp##type##valbytes##_##tagbytes##bt); \
+ }
+
+#define TYPES(card, tagbytes) \
+ F(card, b, 1, tagbytes) \
+ F(card, v, 4, tagbytes) \
+ F(card, v, 8, tagbytes) \
+ F(card, z, 4, tagbytes) \
+ F(card, z, 8, tagbytes)
+
+#define TAGBYTES(card) \
+ TYPES(card, 1) \
+ TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef z_ZZ
+#undef b_ZZ
+#undef v_ZZ
+#undef o_ONEOF
+#undef s_ONEOF
+#undef r_ONEOF
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+
+/* fixed fields ***************************************************************/
+
+UPB_FORCEINLINE
+static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes, upb_card card,
+ _upb_field_parser *packed) {
+ void *dst;
+ fastdecode_arr farr;
+
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
+ return packed(UPB_PARSE_ARGS);
+ }
+ RETURN_GENERIC("fixed field tag mismatch\n");
+ }
+
+ dst =
+ fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
+ if (card == CARD_r) {
+ if (UPB_UNLIKELY(!dst)) {
+ RETURN_GENERIC("couldn't allocate array in arena\n");
+ }
+ }
+
+
+again:
+ if (card == CARD_r) {
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes);
+ }
+
+ ptr += tagbytes;
+ memcpy(dst, ptr, valbytes);
+ ptr += valbytes;
+
+ if (card == CARD_r) {
+ fastdecode_nextret ret =
+ fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
+ switch (ret.next) {
+ case FD_NEXT_SAMEFIELD:
+ dst = ret.dst;
+ goto again;
+ case FD_NEXT_OTHERFIELD:
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ case FD_NEXT_ATLIMIT:
+ return ptr;
+ }
+ }
+
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes,
+ _upb_field_parser *unpacked) {
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ if (fastdecode_flippacked(&data, tagbytes)) {
+ return unpacked(UPB_PARSE_ARGS);
+ } else {
+ RETURN_GENERIC("varint field tag mismatch\n");
+ }
+ }
+
+ ptr += tagbytes;
+ int size = (uint8_t)ptr[0];
+ ptr++;
+ if (size & 0x80) {
+ ptr = fastdecode_longsize(ptr, &size);
+ }
+
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) ||
+ (size % valbytes) != 0) {
+ return fastdecode_err(d);
+ }
+
+ upb_array **arr_p = fastdecode_fieldmem(msg, data);
+ upb_array *arr = *arr_p;
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+ int elems = size / valbytes;
+
+ if (UPB_LIKELY(!arr)) {
+ *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2);
+ if (!arr) {
+ return fastdecode_err(d);
+ }
+ } else {
+ _upb_array_resize(arr, elems, &d->arena);
+ }
+
+ char *dst = _upb_array_ptr(arr);
+ memcpy(dst, ptr, size);
+ arr->len = elems;
+
+ return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes,
+ int valbytes, upb_card card,
+ _upb_field_parser *unpacked,
+ _upb_field_parser *packed) {
+ if (card == CARD_p) {
+ return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked);
+ } else {
+ return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card,
+ packed);
+ }
+}
+
+/* Generate all combinations:
+ * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
+
+#define F(card, valbytes, tagbytes) \
+ UPB_NOINLINE \
+ const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+ return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \
+ &upb_ppf##valbytes##_##tagbytes##bt, \
+ &upb_prf##valbytes##_##tagbytes##bt); \
+ }
+
+#define TYPES(card, tagbytes) \
+ F(card, 4, tagbytes) \
+ F(card, 8, tagbytes)
+
+#define TAGBYTES(card) \
+ TYPES(card, 1) \
+ TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+typedef const char *fastdecode_copystr_func(struct upb_decstate *d,
+ const char *ptr, upb_msg *msg,
+ const upb_msglayout *table,
+ uint64_t hasbits, upb_strview *dst);
+
+UPB_NOINLINE
+static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table,
+ uint64_t hasbits, upb_strview *dst) {
+ if (!decode_verifyutf8_inl(dst->data, dst->size)) {
+ return fastdecode_err(d);
+ }
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longstring(struct upb_decstate *d,
+ const char *ptr, upb_msg *msg,
+ intptr_t table, uint64_t hasbits,
+ upb_strview *dst,
+ bool validate_utf8) {
+ int size = (uint8_t)ptr[0]; // Could plumb through hasbits.
+ ptr++;
+ if (size & 0x80) {
+ ptr = fastdecode_longsize(ptr, &size);
+ }
+
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) {
+ dst->size = 0;
+ return fastdecode_err(d);
+ }
+
+ if (d->alias) {
+ dst->data = ptr;
+ dst->size = size;
+ } else {
+ char *data = upb_arena_malloc(&d->arena, size);
+ if (!data) {
+ return fastdecode_err(d);
+ }
+ memcpy(data, ptr, size);
+ dst->data = data;
+ dst->size = size;
+ }
+
+ if (validate_utf8) {
+ return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst);
+ } else {
+ return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
+ }
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_utf8(struct upb_decstate *d,
+ const char *ptr, upb_msg *msg,
+ intptr_t table, uint64_t hasbits,
+ upb_strview *dst) {
+ return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_noutf8(struct upb_decstate *d,
+ const char *ptr, upb_msg *msg,
+ intptr_t table,
+ uint64_t hasbits,
+ upb_strview *dst) {
+ return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size,
+ int copy, char *data, upb_strview *dst) {
+ d->arena.head.ptr += copy;
+ dst->data = data;
+ UPB_UNPOISON_MEMORY_REGION(data, copy);
+ memcpy(data, ptr, copy);
+ UPB_POISON_MEMORY_REGION(data + size, copy - size);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes,
+ upb_card card, bool validate_utf8) {
+ upb_strview *dst;
+ fastdecode_arr farr;
+ int64_t size;
+ size_t arena_has;
+ size_t common_has;
+ char *buf;
+
+ UPB_ASSERT(!d->alias);
+ UPB_ASSERT(fastdecode_checktag(data, tagbytes));
+
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+ sizeof(upb_strview), card);
+
+again:
+ if (card == CARD_r) {
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
+ }
+
+ size = (uint8_t)ptr[tagbytes];
+ ptr += tagbytes + 1;
+ dst->size = size;
+
+ buf = d->arena.head.ptr;
+ arena_has = _upb_arenahas(&d->arena);
+ common_has = UPB_MIN(arena_has, (d->end - ptr) + 16);
+
+ if (UPB_LIKELY(size <= 15 - tagbytes)) {
+ if (arena_has < 16) goto longstr;
+ d->arena.head.ptr += 16;
+ memcpy(buf, ptr - tagbytes - 1, 16);
+ dst->data = buf + tagbytes + 1;
+ } else if (UPB_LIKELY(size <= 32)) {
+ if (UPB_UNLIKELY(common_has < 32)) goto longstr;
+ fastdecode_docopy(d, ptr, size, 32, buf, dst);
+ } else if (UPB_LIKELY(size <= 64)) {
+ if (UPB_UNLIKELY(common_has < 64)) goto longstr;
+ fastdecode_docopy(d, ptr, size, 64, buf, dst);
+ } else if (UPB_LIKELY(size < 128)) {
+ if (UPB_UNLIKELY(common_has < 128)) goto longstr;
+ fastdecode_docopy(d, ptr, size, 128, buf, dst);
+ } else {
+ goto longstr;
+ }
+
+ ptr += size;
+
+ if (card == CARD_r) {
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
+ return fastdecode_err(d);
+ }
+ fastdecode_nextret ret = fastdecode_nextrepeated(
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
+ switch (ret.next) {
+ case FD_NEXT_SAMEFIELD:
+ dst = ret.dst;
+ goto again;
+ case FD_NEXT_OTHERFIELD:
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ case FD_NEXT_ATLIMIT:
+ return ptr;
+ }
+ }
+
+ if (card != CARD_r && validate_utf8) {
+ return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
+ }
+
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+
+longstr:
+ ptr--;
+ if (validate_utf8) {
+ return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
+ } else {
+ return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
+ }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes,
+ upb_card card, _upb_field_parser *copyfunc,
+ bool validate_utf8) {
+ upb_strview *dst;
+ fastdecode_arr farr;
+ int64_t size;
+
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ RETURN_GENERIC("string field tag mismatch\n");
+ }
+
+ if (UPB_UNLIKELY(!d->alias)) {
+ return copyfunc(UPB_PARSE_ARGS);
+ }
+
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+ sizeof(upb_strview), card);
+
+again:
+ if (card == CARD_r) {
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
+ }
+
+ size = (int8_t)ptr[tagbytes];
+ ptr += tagbytes + 1;
+ dst->data = ptr;
+ dst->size = size;
+
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) {
+ ptr--;
+ if (validate_utf8) {
+ return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
+ } else {
+ return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
+ }
+ }
+
+ ptr += size;
+
+ if (card == CARD_r) {
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
+ return fastdecode_err(d);
+ }
+ fastdecode_nextret ret = fastdecode_nextrepeated(
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
+ switch (ret.next) {
+ case FD_NEXT_SAMEFIELD:
+ dst = ret.dst;
+ if (UPB_UNLIKELY(!d->alias)) {
+ // Buffer flipped and we can't alias any more. Bounce to copyfunc(),
+ // but via dispatch since we need to reload table data also.
+ fastdecode_commitarr(dst, &farr, sizeof(upb_strview));
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ }
+ goto again;
+ case FD_NEXT_OTHERFIELD:
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ case FD_NEXT_ATLIMIT:
+ return ptr;
+ }
+ }
+
+ if (card != CARD_r && validate_utf8) {
+ return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
+ }
+
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+/* Generate all combinations:
+ * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
+
+#define s_VALIDATE true
+#define b_VALIDATE false
+
+#define F(card, tagbytes, type) \
+ UPB_NOINLINE \
+ const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+ return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \
+ type##_VALIDATE); \
+ } \
+ const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+ return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card, \
+ &upb_c##card##type##_##tagbytes##bt, \
+ type##_VALIDATE); \
+ }
+
+#define UTF8(card, tagbytes) \
+ F(card, tagbytes, s) \
+ F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+ UTF8(card, 1) \
+ UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef s_VALIDATE
+#undef b_VALIDATE
+#undef F
+#undef TAGBYTES
+
+/* message fields *************************************************************/
+
+UPB_INLINE
+upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l,
+ int msg_ceil_bytes) {
+ size_t size = l->size + sizeof(upb_msg_internal);
+ char *msg_data;
+ if (UPB_LIKELY(msg_ceil_bytes > 0 &&
+ _upb_arenahas(&d->arena) >= msg_ceil_bytes)) {
+ UPB_ASSERT(size <= (size_t)msg_ceil_bytes);
+ msg_data = d->arena.head.ptr;
+ d->arena.head.ptr += size;
+ UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes);
+ memset(msg_data, 0, msg_ceil_bytes);
+ UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size);
+ } else {
+ msg_data = (char*)upb_arena_malloc(&d->arena, size);
+ memset(msg_data, 0, size);
+ }
+ return msg_data + sizeof(upb_msg_internal);
+}
+
+typedef struct {
+ intptr_t table;
+ upb_msg *msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr,
+ void *ctx) {
+ fastdecode_submsgdata *submsg = ctx;
+ ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0);
+ UPB_ASSUME(ptr != NULL);
+ return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
+ int msg_ceil_bytes, upb_card card) {
+
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+ RETURN_GENERIC("submessage field tag mismatch\n");
+ }
+
+ if (--d->depth == 0) return fastdecode_err(d);
+
+ upb_msg **dst;
+ uint32_t submsg_idx = (data >> 16) & 0xff;
+ const upb_msglayout *tablep = decode_totablep(table);
+ const upb_msglayout *subtablep = tablep->submsgs[submsg_idx];
+ fastdecode_submsgdata submsg = {decode_totable(subtablep)};
+ fastdecode_arr farr;
+
+ if (subtablep->table_mask == (uint8_t)-1) {
+ RETURN_GENERIC("submessage doesn't have fast tables.");
+ }
+
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+ sizeof(upb_msg *), card);
+
+ if (card == CARD_s) {
+ *(uint32_t*)msg |= hasbits;
+ hasbits = 0;
+ }
+
+again:
+ if (card == CARD_r) {
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*));
+ }
+
+ submsg.msg = *dst;
+
+ if (card == CARD_r || UPB_LIKELY(!submsg.msg)) {
+ *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes);
+ }
+
+ ptr += tagbytes;
+ ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg);
+
+ if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) {
+ return fastdecode_err(d);
+ }
+
+ if (card == CARD_r) {
+ fastdecode_nextret ret = fastdecode_nextrepeated(
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *));
+ switch (ret.next) {
+ case FD_NEXT_SAMEFIELD:
+ dst = ret.dst;
+ goto again;
+ case FD_NEXT_OTHERFIELD:
+ d->depth++;
+ return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+ case FD_NEXT_ATLIMIT:
+ d->depth++;
+ return ptr;
+ }
+ }
+
+ d->depth++;
+ return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+#define F(card, tagbytes, size_ceil, ceil_arg) \
+ const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \
+ UPB_PARSE_PARAMS) { \
+ return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \
+ }
+
+#define SIZES(card, tagbytes) \
+ F(card, tagbytes, 64, 64) \
+ F(card, tagbytes, 128, 128) \
+ F(card, tagbytes, 192, 192) \
+ F(card, tagbytes, 256, 256) \
+ F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+ SIZES(card, 1) \
+ SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#endif /* UPB_FASTTABLE */
diff --git a/contrib/libs/grpc/third_party/upb/upb/decode_fast.h b/contrib/libs/grpc/third_party/upb/upb/decode_fast.h
new file mode 100644
index 0000000000..6d56d12477
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/decode_fast.h
@@ -0,0 +1,126 @@
+// These are the specialized field parser functions for the fast parser.
+// Generated tables will refer to these by name.
+//
+// The function names are encoded with names like:
+//
+// // 123 4
+// upb_pss_1bt(); // Parse singular string, 1 byte tag.
+//
+// In position 1:
+// - 'p' for parse, most function use this
+// - 'c' for copy, for when we are copying strings instead of aliasing
+//
+// In position 2 (cardinality):
+// - 's' for singular, with or without hasbit
+// - 'o' for oneof
+// - 'r' for non-packed repeated
+// - 'p' for packed repeated
+//
+// In position 3 (type):
+// - 'b1' for bool
+// - 'v4' for 4-byte varint
+// - 'v8' for 8-byte varint
+// - 'z4' for zig-zag-encoded 4-byte varint
+// - 'z8' for zig-zag-encoded 8-byte varint
+// - 'f4' for 4-byte fixed
+// - 'f8' for 8-byte fixed
+// - 'm' for sub-message
+// - 's' for string (validate UTF-8)
+// - 'b' for bytes
+//
+// In position 4 (tag length):
+// - '1' for one-byte tags (field numbers 1-15)
+// - '2' for two-byte tags (field numbers 16-2048)
+
+#ifndef UPB_DECODE_FAST_H_
+#define UPB_DECODE_FAST_H_
+
+#include "upb/msg.h"
+
+struct upb_decstate;
+
+// The fallback, generic parsing function that can handle any field type.
+// This just uses the regular (non-fast) parser to parse a single field.
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table, uint64_t hasbits,
+ uint64_t data);
+
+#define UPB_PARSE_PARAMS \
+ struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+ uint64_t hasbits, uint64_t data
+
+/* primitive fields ***********************************************************/
+
+#define F(card, type, valbytes, tagbytes) \
+ const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define TYPES(card, tagbytes) \
+ F(card, b, 1, tagbytes) \
+ F(card, v, 4, tagbytes) \
+ F(card, v, 8, tagbytes) \
+ F(card, z, 4, tagbytes) \
+ F(card, z, 8, tagbytes) \
+ F(card, f, 4, tagbytes) \
+ F(card, f, 8, tagbytes)
+
+#define TAGBYTES(card) \
+ TYPES(card, 1) \
+ TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+#define F(card, tagbytes, type) \
+ const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \
+ const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define UTF8(card, tagbytes) \
+ F(card, tagbytes, s) \
+ F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+ UTF8(card, 1) \
+ UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef F
+#undef TAGBYTES
+
+/* sub-message fields *********************************************************/
+
+#define F(card, tagbytes, size_ceil, ceil_arg) \
+ const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS);
+
+#define SIZES(card, tagbytes) \
+ F(card, tagbytes, 64, 64) \
+ F(card, tagbytes, 128, 128) \
+ F(card, tagbytes, 192, 192) \
+ F(card, tagbytes, 256, 256) \
+ F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+ SIZES(card, 1) \
+ SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#undef UPB_PARSE_PARAMS
+
+#endif /* UPB_DECODE_FAST_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.c b/contrib/libs/grpc/third_party/upb/upb/def.c
new file mode 100644
index 0000000000..4ba553a69c
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/def.c
@@ -0,0 +1,2178 @@
+
+#include "upb/def.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "google/protobuf/descriptor.upb.h"
+#include "upb/port_def.inc"
+
+typedef struct {
+ size_t len;
+ char str[1]; /* Null-terminated string data follows. */
+} str_t;
+
+struct upb_fielddef {
+ const upb_filedef *file;
+ const upb_msgdef *msgdef;
+ const char *full_name;
+ const char *json_name;
+ union {
+ int64_t sint;
+ uint64_t uint;
+ double dbl;
+ float flt;
+ bool boolean;
+ str_t *str;
+ } defaultval;
+ const upb_oneofdef *oneof;
+ union {
+ const upb_msgdef *msgdef;
+ const upb_enumdef *enumdef;
+ const google_protobuf_FieldDescriptorProto *unresolved;
+ } sub;
+ uint32_t number_;
+ uint16_t index_;
+ uint16_t layout_index;
+ uint32_t selector_base; /* Used to index into a upb::Handlers table. */
+ bool is_extension_;
+ bool lazy_;
+ bool packed_;
+ bool proto3_optional_;
+ upb_descriptortype_t type_;
+ upb_label_t label_;
+};
+
+struct upb_msgdef {
+ const upb_msglayout *layout;
+ const upb_filedef *file;
+ const char *full_name;
+ uint32_t selector_count;
+ uint32_t submsg_field_count;
+
+ /* Tables for looking up fields by number and name. */
+ upb_inttable itof;
+ upb_strtable ntof;
+
+ const upb_fielddef *fields;
+ const upb_oneofdef *oneofs;
+ int field_count;
+ int oneof_count;
+ int real_oneof_count;
+
+ /* Is this a map-entry message? */
+ bool map_entry;
+ upb_wellknowntype_t well_known_type;
+
+ /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+struct upb_enumdef {
+ const upb_filedef *file;
+ const char *full_name;
+ upb_strtable ntoi;
+ upb_inttable iton;
+ int32_t defaultval;
+};
+
+struct upb_oneofdef {
+ const upb_msgdef *parent;
+ const char *full_name;
+ int field_count;
+ bool synthetic;
+ const upb_fielddef **fields;
+ upb_strtable ntof;
+ upb_inttable itof;
+};
+
+struct upb_filedef {
+ const char *name;
+ const char *package;
+ const char *phpprefix;
+ const char *phpnamespace;
+
+ const upb_filedef **deps;
+ const upb_msgdef *msgs;
+ const upb_enumdef *enums;
+ const upb_fielddef *exts;
+ const upb_symtab *symtab;
+
+ int dep_count;
+ int msg_count;
+ int enum_count;
+ int ext_count;
+ upb_syntax_t syntax;
+};
+
+struct upb_symtab {
+ upb_arena *arena;
+ upb_strtable syms; /* full_name -> packed def ptr */
+ upb_strtable files; /* file_name -> upb_filedef* */
+ size_t bytes_loaded;
+};
+
+/* Inside a symtab we store tagged pointers to specific def types. */
+typedef enum {
+ UPB_DEFTYPE_FIELD = 0,
+
+ /* Only inside symtab table. */
+ UPB_DEFTYPE_MSG = 1,
+ UPB_DEFTYPE_ENUM = 2,
+
+ /* Only inside message table. */
+ UPB_DEFTYPE_ONEOF = 1,
+ UPB_DEFTYPE_FIELD_JSONNAME = 2
+} upb_deftype_t;
+
+static const void *unpack_def(upb_value v, upb_deftype_t type) {
+ uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+ return (num & 3) == type ? (const void*)(num & ~3) : NULL;
+}
+
+static upb_value pack_def(const void *ptr, upb_deftype_t type) {
+ uintptr_t num = (uintptr_t)ptr | type;
+ return upb_value_constptr((const void*)num);
+}
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+ return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+ return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+ return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static const char *shortdefname(const char *fullname) {
+ const char *p;
+
+ if (fullname == NULL) {
+ return NULL;
+ } else if ((p = strrchr(fullname, '.')) == NULL) {
+ /* No '.' in the name, return the full string. */
+ return fullname;
+ } else {
+ /* Return one past the last '.'. */
+ return p + 1;
+ }
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+ uint32_t ret = upb_fielddef_number(f);
+ const uint32_t high_bit = 1 << 30;
+ UPB_ASSERT(ret < high_bit);
+ if (!upb_fielddef_issubmsg(f))
+ ret |= high_bit;
+ return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+ const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+ const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+ return field_rank(f1) - field_rank(f2);
+}
+
+/* A few implementation details of handlers. We put these here to avoid
+ * a def -> handlers dependency. */
+
+#define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */
+
+static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
+ return upb_fielddef_isseq(f) ? 2 : 0;
+}
+
+static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
+ uint32_t ret = 1;
+ if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
+ if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
+ if (upb_fielddef_issubmsg(f)) {
+ /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
+ ret += 0;
+ if (upb_fielddef_lazy(f)) {
+ /* STARTSTR/ENDSTR/STRING (for lazy) */
+ ret += 3;
+ }
+ }
+ return ret;
+}
+
+static void upb_status_setoom(upb_status *status) {
+ upb_status_seterrmsg(status, "out of memory");
+}
+
+static void assign_msg_wellknowntype(upb_msgdef *m) {
+ const char *name = upb_msgdef_fullname(m);
+ if (name == NULL) {
+ m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+ return;
+ }
+ if (!strcmp(name, "google.protobuf.Any")) {
+ m->well_known_type = UPB_WELLKNOWN_ANY;
+ } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+ m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
+ } else if (!strcmp(name, "google.protobuf.Duration")) {
+ m->well_known_type = UPB_WELLKNOWN_DURATION;
+ } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+ m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
+ } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+ m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
+ } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+ m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
+ } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+ m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
+ } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+ m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
+ } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+ m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
+ } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+ m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
+ } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+ m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
+ } else if (!strcmp(name, "google.protobuf.StringValue")) {
+ m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
+ } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+ m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
+ } else if (!strcmp(name, "google.protobuf.Value")) {
+ m->well_known_type = UPB_WELLKNOWN_VALUE;
+ } else if (!strcmp(name, "google.protobuf.ListValue")) {
+ m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
+ } else if (!strcmp(name, "google.protobuf.Struct")) {
+ m->well_known_type = UPB_WELLKNOWN_STRUCT;
+ } else {
+ m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+ }
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+ return e->full_name;
+}
+
+const char *upb_enumdef_name(const upb_enumdef *e) {
+ return shortdefname(e->full_name);
+}
+
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
+ return e->file;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+ UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
+ return e->defaultval;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+ return (int)upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+ /* We iterate over the ntoi table, to account for duplicate numbers. */
+ upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+ size_t len, int32_t *num) {
+ upb_value v;
+ if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+ return false;
+ }
+ if (num) *num = upb_value_getint32(v);
+ return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+ upb_value v;
+ return upb_inttable_lookup32(&def->iton, num, &v) ?
+ upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+ return upb_strtable_iter_key(iter).data;
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+ return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+const char *upb_fielddef_fullname(const upb_fielddef *f) {
+ return f->full_name;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+ switch (f->type_) {
+ case UPB_DESCRIPTOR_TYPE_DOUBLE:
+ return UPB_TYPE_DOUBLE;
+ case UPB_DESCRIPTOR_TYPE_FLOAT:
+ return UPB_TYPE_FLOAT;
+ case UPB_DESCRIPTOR_TYPE_INT64:
+ case UPB_DESCRIPTOR_TYPE_SINT64:
+ case UPB_DESCRIPTOR_TYPE_SFIXED64:
+ return UPB_TYPE_INT64;
+ case UPB_DESCRIPTOR_TYPE_INT32:
+ case UPB_DESCRIPTOR_TYPE_SFIXED32:
+ case UPB_DESCRIPTOR_TYPE_SINT32:
+ return UPB_TYPE_INT32;
+ case UPB_DESCRIPTOR_TYPE_UINT64:
+ case UPB_DESCRIPTOR_TYPE_FIXED64:
+ return UPB_TYPE_UINT64;
+ case UPB_DESCRIPTOR_TYPE_UINT32:
+ case UPB_DESCRIPTOR_TYPE_FIXED32:
+ return UPB_TYPE_UINT32;
+ case UPB_DESCRIPTOR_TYPE_ENUM:
+ return UPB_TYPE_ENUM;
+ case UPB_DESCRIPTOR_TYPE_BOOL:
+ return UPB_TYPE_BOOL;
+ case UPB_DESCRIPTOR_TYPE_STRING:
+ return UPB_TYPE_STRING;
+ case UPB_DESCRIPTOR_TYPE_BYTES:
+ return UPB_TYPE_BYTES;
+ case UPB_DESCRIPTOR_TYPE_GROUP:
+ case UPB_DESCRIPTOR_TYPE_MESSAGE:
+ return UPB_TYPE_MESSAGE;
+ }
+ UPB_UNREACHABLE();
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+ return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+ return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+ return f->label_;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+ return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+ return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+ return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+ return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+ return shortdefname(f->full_name);
+}
+
+const char *upb_fielddef_jsonname(const upb_fielddef *f) {
+ return f->json_name;
+}
+
+uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
+ return f->selector_base;
+}
+
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
+ return f->file;
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+ return f->msgdef;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+ return f->oneof;
+}
+
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
+ if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
+ return f->oneof;
+}
+
+static void chkdefaulttype(const upb_fielddef *f, int ctype) {
+ UPB_UNUSED(f);
+ UPB_UNUSED(ctype);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_INT64);
+ return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_INT32);
+ return (int32_t)f->defaultval.sint;
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_UINT64);
+ return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_UINT32);
+ return (uint32_t)f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_BOOL);
+ return f->defaultval.boolean;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_FLOAT);
+ return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+ chkdefaulttype(f, UPB_TYPE_DOUBLE);
+ return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+ str_t *str = f->defaultval.str;
+ UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+ upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+ upb_fielddef_type(f) == UPB_TYPE_ENUM);
+ if (str) {
+ if (len) *len = str->len;
+ return str->str;
+ } else {
+ if (len) *len = 0;
+ return NULL;
+ }
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+ return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+ return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL;
+}
+
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
+ return &f->msgdef->layout->fields[f->layout_index];
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+ return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+ return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+ upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+ return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+ return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+ return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+ upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+ return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+ if (upb_fielddef_isseq(f)) return false;
+ return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
+ f->file->syntax == UPB_SYNTAX_PROTO2;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+ return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+ return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+ return m->full_name;
+}
+
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
+ return m->file;
+}
+
+const char *upb_msgdef_name(const upb_msgdef *m) {
+ return shortdefname(m->full_name);
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+ return m->file->syntax;
+}
+
+size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
+ return m->selector_count;
+}
+
+uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
+ return m->submsg_field_count;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+ upb_value val;
+ return upb_inttable_lookup32(&m->itof, i, &val) ?
+ upb_value_getconstptr(val) : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+ size_t len) {
+ upb_value val;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return unpack_def(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+ size_t len) {
+ upb_value val;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return unpack_def(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o) {
+ upb_value val;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return false;
+ }
+
+ *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
+ *f = unpack_def(val, UPB_DEFTYPE_FIELD);
+ return *o || *f; /* False if this was a JSON name. */
+}
+
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+ const char *name, size_t len) {
+ upb_value val;
+ const upb_fielddef* f;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ f = unpack_def(val, UPB_DEFTYPE_FIELD);
+ if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+ return f;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+ return m->field_count;
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+ return m->oneof_count;
+}
+
+int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
+ return m->real_oneof_count;
+}
+
+int upb_msgdef_fieldcount(const upb_msgdef *m) {
+ return m->field_count;
+}
+
+int upb_msgdef_oneofcount(const upb_msgdef *m) {
+ return m->oneof_count;
+}
+
+int upb_msgdef_realoneofcount(const upb_msgdef *m) {
+ return m->real_oneof_count;
+}
+
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
+ return m->layout;
+}
+
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) {
+ UPB_ASSERT(i >= 0 && i < m->field_count);
+ return &m->fields[i];
+}
+
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) {
+ UPB_ASSERT(i >= 0 && i < m->oneof_count);
+ return &m->oneofs[i];
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+ return m->map_entry;
+}
+
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
+ return m->well_known_type;
+}
+
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
+ upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+ return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+ type <= UPB_WELLKNOWN_UINT32VALUE;
+}
+
+bool upb_msgdef_iswrapper(const upb_msgdef *m) {
+ upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+ return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+ type <= UPB_WELLKNOWN_BOOLVALUE;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+ upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+ return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+ return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+ upb_inttable_iter_setdone(iter);
+}
+
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+ const upb_msg_field_iter * iter2) {
+ return upb_inttable_iter_isequal(iter1, iter2);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+ upb_strtable_begin(iter, &m->ntof);
+ /* We need to skip past any initial fields. */
+ while (!upb_strtable_done(iter) &&
+ !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
+ upb_strtable_next(iter);
+ }
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+ /* We need to skip past fields to return only oneofs. */
+ do {
+ upb_strtable_next(iter);
+ } while (!upb_strtable_done(iter) &&
+ !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
+}
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+ return upb_strtable_done(iter);
+}
+
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+ return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+ upb_strtable_iter_setdone(iter);
+}
+
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+ const upb_msg_oneof_iter *iter2) {
+ return upb_strtable_iter_isequal(iter1, iter2);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+ return shortdefname(o->full_name);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+ return o->parent;
+}
+
+int upb_oneofdef_fieldcount(const upb_oneofdef *o) {
+ return o->field_count;
+}
+
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) {
+ UPB_ASSERT(i < o->field_count);
+ return o->fields[i];
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+ return o->field_count;
+}
+
+uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
+ return o - o->parent->oneofs;
+}
+
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
+ return o->synthetic;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+ const char *name, size_t length) {
+ upb_value val;
+ return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+ upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+ upb_value val;
+ return upb_inttable_lookup32(&o->itof, num, &val) ?
+ upb_value_getptr(val) : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+ upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+ upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+ return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+ return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+ upb_inttable_iter_setdone(iter);
+}
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f) {
+ return f->name;
+}
+
+const char *upb_filedef_package(const upb_filedef *f) {
+ return f->package;
+}
+
+const char *upb_filedef_phpprefix(const upb_filedef *f) {
+ return f->phpprefix;
+}
+
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+ return f->phpnamespace;
+}
+
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+ return f->syntax;
+}
+
+int upb_filedef_msgcount(const upb_filedef *f) {
+ return f->msg_count;
+}
+
+int upb_filedef_depcount(const upb_filedef *f) {
+ return f->dep_count;
+}
+
+int upb_filedef_enumcount(const upb_filedef *f) {
+ return f->enum_count;
+}
+
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
+ return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
+}
+
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
+ return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
+}
+
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
+ return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
+}
+
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f) {
+ return f->symtab;
+}
+
+void upb_symtab_free(upb_symtab *s) {
+ upb_arena_free(s->arena);
+ upb_gfree(s);
+}
+
+upb_symtab *upb_symtab_new(void) {
+ upb_symtab *s = upb_gmalloc(sizeof(*s));
+ upb_alloc *alloc;
+
+ if (!s) {
+ return NULL;
+ }
+
+ s->arena = upb_arena_new();
+ s->bytes_loaded = 0;
+ alloc = upb_arena_alloc(s->arena);
+
+ if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, 32, alloc) ||
+ !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, 4, alloc)) {
+ upb_arena_free(s->arena);
+ upb_gfree(s);
+ s = NULL;
+ }
+ return s;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+ upb_value v;
+ return upb_strtable_lookup(&s->syms, sym, &v) ?
+ unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
+ size_t len) {
+ upb_value v;
+ return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
+ unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+ upb_value v;
+ return upb_strtable_lookup(&s->syms, sym, &v) ?
+ unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
+ upb_value v;
+ return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+ : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile2(
+ const upb_symtab *s, const char *name, size_t len) {
+ upb_value v;
+ return upb_strtable_lookup2(&s->files, name, len, &v) ?
+ upb_value_getconstptr(v) : NULL;
+}
+
+int upb_symtab_filecount(const upb_symtab *s) {
+ return (int)upb_strtable_count(&s->files);
+}
+
+/* Code to build defs from descriptor protos. *********************************/
+
+/* There is a question of how much validation to do here. It will be difficult
+ * to perfectly match the amount of validation performed by proto2. But since
+ * this code is used to directly build defs from Ruby (for example) we do need
+ * to validate important constraints like uniqueness of names and numbers. */
+
+#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); }
+
+typedef struct {
+ upb_symtab *symtab;
+ upb_filedef *file; /* File we are building. */
+ upb_arena *file_arena; /* Allocate defs here. */
+ upb_alloc *alloc; /* Alloc of file_arena, for tables. */
+ const upb_msglayout **layouts; /* NULL if we should build layouts. */
+ upb_status *status; /* Record errors here. */
+ jmp_buf err; /* longjmp() on error. */
+} symtab_addctx;
+
+UPB_NORETURN UPB_NOINLINE
+static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) {
+ va_list argp;
+ va_start(argp, fmt);
+ upb_status_vseterrf(ctx->status, fmt, argp);
+ va_end(argp);
+ UPB_LONGJMP(ctx->err, 1);
+}
+
+UPB_NORETURN UPB_NOINLINE
+static void symtab_oomerr(symtab_addctx *ctx) {
+ upb_status_setoom(ctx->status);
+ UPB_LONGJMP(ctx->err, 1);
+}
+
+void *symtab_alloc(symtab_addctx *ctx, size_t bytes) {
+ void *ret = upb_arena_malloc(ctx->file_arena, bytes);
+ if (!ret) symtab_oomerr(ctx);
+ return ret;
+}
+
+static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) {
+ const char *str = name.data;
+ size_t len = name.size;
+ bool start = true;
+ size_t i;
+ for (i = 0; i < len; i++) {
+ char c = str[i];
+ if (c == '.') {
+ if (start || !full) {
+ symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str);
+ }
+ start = true;
+ } else if (start) {
+ if (!upb_isletter(c)) {
+ symtab_errf(
+ ctx,
+ "invalid name: path components must start with a letter (%.*s)",
+ (int)len, str);
+ }
+ start = false;
+ } else {
+ if (!upb_isalphanum(c)) {
+ symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)",
+ (int)len, str);
+ }
+ }
+ }
+ if (start) {
+ symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str);
+ }
+}
+
+static size_t div_round_up(size_t n, size_t d) {
+ return (n + d - 1) / d;
+}
+
+static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ return 8;
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_FLOAT:
+ return 4;
+ case UPB_TYPE_BOOL:
+ return 1;
+ case UPB_TYPE_MESSAGE:
+ return sizeof(void*);
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_STRING:
+ return sizeof(upb_strview);
+ }
+ UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
+ if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
+ upb_map_entry ent;
+ UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
+ return sizeof(ent.k);
+ } else if (upb_fielddef_isseq(f)) {
+ return sizeof(void*);
+ } else {
+ return upb_msgval_sizeof(upb_fielddef_type(f));
+ }
+}
+
+static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
+ uint32_t ret;
+
+ l->size = UPB_ALIGN_UP(l->size, size);
+ ret = l->size;
+ l->size += size;
+ return ret;
+}
+
+static int field_number_cmp(const void *p1, const void *p2) {
+ const upb_msglayout_field *f1 = p1;
+ const upb_msglayout_field *f2 = p2;
+ return f1->number - f2->number;
+}
+
+static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) {
+ int i;
+ int n = upb_msgdef_numfields(m);
+ for (i = 0; i < n; i++) {
+ upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
+ UPB_ASSERT(f);
+ f->layout_index = i;
+ }
+}
+
+/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
+ * It computes a dynamic layout for all of the fields in |m|. */
+static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
+ upb_msglayout *l = (upb_msglayout*)m->layout;
+ upb_msg_field_iter it;
+ upb_msg_oneof_iter oit;
+ size_t hasbit;
+ size_t submsg_count = m->submsg_field_count;
+ const upb_msglayout **submsgs;
+ upb_msglayout_field *fields;
+
+ memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry));
+
+ fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields));
+ submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs));
+
+ l->field_count = upb_msgdef_numfields(m);
+ l->fields = fields;
+ l->submsgs = submsgs;
+ l->table_mask = 0;
+
+ /* TODO(haberman): initialize fast tables so that reflection-based parsing
+ * can get the same speeds as linked-in types. */
+ l->fasttable[0].field_parser = &fastdecode_generic;
+ l->fasttable[0].field_data = 0;
+
+ if (upb_msgdef_mapentry(m)) {
+ /* TODO(haberman): refactor this method so this special case is more
+ * elegant. */
+ const upb_fielddef *key = upb_msgdef_itof(m, 1);
+ const upb_fielddef *val = upb_msgdef_itof(m, 2);
+ fields[0].number = 1;
+ fields[1].number = 2;
+ fields[0].label = UPB_LABEL_OPTIONAL;
+ fields[1].label = UPB_LABEL_OPTIONAL;
+ fields[0].presence = 0;
+ fields[1].presence = 0;
+ fields[0].descriptortype = upb_fielddef_descriptortype(key);
+ fields[1].descriptortype = upb_fielddef_descriptortype(val);
+ fields[0].offset = 0;
+ fields[1].offset = sizeof(upb_strview);
+ fields[1].submsg_index = 0;
+
+ if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
+ submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
+ }
+
+ l->field_count = 2;
+ l->size = 2 * sizeof(upb_strview);
+ l->size = UPB_ALIGN_UP(l->size, 8);
+ return;
+ }
+
+ /* Allocate data offsets in three stages:
+ *
+ * 1. hasbits.
+ * 2. regular fields.
+ * 3. oneof fields.
+ *
+ * OPT: There is a lot of room for optimization here to minimize the size.
+ */
+
+ /* Allocate hasbits and set basic field attributes. */
+ submsg_count = 0;
+ for (upb_msg_field_begin(&it, m), hasbit = 0;
+ !upb_msg_field_done(&it);
+ upb_msg_field_next(&it)) {
+ upb_fielddef* f = upb_msg_iter_field(&it);
+ upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
+
+ field->number = upb_fielddef_number(f);
+ field->descriptortype = upb_fielddef_descriptortype(f);
+ field->label = upb_fielddef_label(f);
+
+ if (field->descriptortype == UPB_DTYPE_STRING &&
+ f->file->syntax == UPB_SYNTAX_PROTO2) {
+ /* See TableDescriptorType() in upbc/generator.cc for details and
+ * rationale. */
+ field->descriptortype = UPB_DTYPE_BYTES;
+ }
+
+ if (upb_fielddef_ismap(f)) {
+ field->label = _UPB_LABEL_MAP;
+ } else if (upb_fielddef_packed(f)) {
+ field->label = _UPB_LABEL_PACKED;
+ }
+
+ if (upb_fielddef_issubmsg(f)) {
+ const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+ field->submsg_index = submsg_count++;
+ submsgs[field->submsg_index] = subm->layout;
+ }
+
+ if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
+ /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
+ * table. This wastes one hasbit, but we don't worry about it for now. */
+ field->presence = ++hasbit;
+ } else {
+ field->presence = 0;
+ }
+ }
+
+ /* Account for space used by hasbits. */
+ l->size = div_round_up(hasbit, 8);
+
+ /* Allocate non-oneof fields. */
+ for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
+ upb_msg_field_next(&it)) {
+ const upb_fielddef* f = upb_msg_iter_field(&it);
+ size_t field_size = upb_msg_fielddefsize(f);
+ size_t index = upb_fielddef_index(f);
+
+ if (upb_fielddef_realcontainingoneof(f)) {
+ /* Oneofs are handled separately below. */
+ continue;
+ }
+
+ fields[index].offset = upb_msglayout_place(l, field_size);
+ }
+
+ /* Allocate oneof fields. Each oneof field consists of a uint32 for the case
+ * and space for the actual data. */
+ for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
+ upb_msg_oneof_next(&oit)) {
+ const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
+ upb_oneof_iter fit;
+
+ size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */
+ size_t field_size = 0;
+ uint32_t case_offset;
+ uint32_t data_offset;
+
+ if (upb_oneofdef_issynthetic(o)) continue;
+
+ /* Calculate field size: the max of all field sizes. */
+ for (upb_oneof_begin(&fit, o);
+ !upb_oneof_done(&fit);
+ upb_oneof_next(&fit)) {
+ const upb_fielddef* f = upb_oneof_iter_field(&fit);
+ field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
+ }
+
+ /* Align and allocate case offset. */
+ case_offset = upb_msglayout_place(l, case_size);
+ data_offset = upb_msglayout_place(l, field_size);
+
+ for (upb_oneof_begin(&fit, o);
+ !upb_oneof_done(&fit);
+ upb_oneof_next(&fit)) {
+ const upb_fielddef* f = upb_oneof_iter_field(&fit);
+ fields[upb_fielddef_index(f)].offset = data_offset;
+ fields[upb_fielddef_index(f)].presence = ~case_offset;
+ }
+ }
+
+ /* Size of the entire structure should be a multiple of its greatest
+ * alignment. TODO: track overall alignment for real? */
+ l->size = UPB_ALIGN_UP(l->size, 8);
+
+ /* Sort fields by number. */
+ qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
+ assign_layout_indices(m, fields);
+}
+
+static void assign_msg_indices(symtab_addctx *ctx, upb_msgdef *m) {
+ /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
+ * lowest indexes, but we do not publicly guarantee this. */
+ upb_msg_field_iter j;
+ int i;
+ uint32_t selector;
+ int n = upb_msgdef_numfields(m);
+ upb_fielddef **fields;
+
+ if (n == 0) {
+ m->selector_count = UPB_STATIC_SELECTOR_COUNT;
+ m->submsg_field_count = 0;
+ return;
+ }
+
+ fields = upb_gmalloc(n * sizeof(*fields));
+
+ m->submsg_field_count = 0;
+ for(i = 0, upb_msg_field_begin(&j, m);
+ !upb_msg_field_done(&j);
+ upb_msg_field_next(&j), i++) {
+ upb_fielddef *f = upb_msg_iter_field(&j);
+ UPB_ASSERT(f->msgdef == m);
+ if (upb_fielddef_issubmsg(f)) {
+ m->submsg_field_count++;
+ }
+ fields[i] = f;
+ }
+
+ qsort(fields, n, sizeof(*fields), cmp_fields);
+
+ selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
+ for (i = 0; i < n; i++) {
+ upb_fielddef *f = fields[i];
+ f->index_ = i;
+ f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
+ selector += upb_handlers_selectorcount(f);
+ }
+ m->selector_count = selector;
+
+ upb_gfree(fields);
+}
+
+static char *strviewdup(symtab_addctx *ctx, upb_strview view) {
+ return upb_strdup2(view.data, view.size, ctx->alloc);
+}
+
+static bool streql2(const char *a, size_t n, const char *b) {
+ return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+static bool streql_view(upb_strview view, const char *b) {
+ return streql2(view.data, view.size, b);
+}
+
+static const char *makefullname(symtab_addctx *ctx, const char *prefix,
+ upb_strview name) {
+ if (prefix) {
+ /* ret = prefix + '.' + name; */
+ size_t n = strlen(prefix);
+ char *ret = symtab_alloc(ctx, n + name.size + 2);
+ strcpy(ret, prefix);
+ ret[n] = '.';
+ memcpy(&ret[n + 1], name.data, name.size);
+ ret[n + 1 + name.size] = '\0';
+ return ret;
+ } else {
+ return strviewdup(ctx, name);
+ }
+}
+
+static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) {
+ int i;
+ int synthetic_count = 0;
+ upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
+
+ for (i = 0; i < m->oneof_count; i++) {
+ upb_oneofdef *o = &mutable_oneofs[i];
+
+ if (o->synthetic && o->field_count != 1) {
+ symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s",
+ o->field_count, upb_oneofdef_name(o));
+ }
+
+ if (o->synthetic) {
+ synthetic_count++;
+ } else if (synthetic_count != 0) {
+ symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s",
+ upb_oneofdef_name(o));
+ }
+
+ o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count);
+ o->field_count = 0;
+ }
+
+ for (i = 0; i < m->field_count; i++) {
+ const upb_fielddef *f = &m->fields[i];
+ upb_oneofdef *o = (upb_oneofdef*)f->oneof;
+ if (o) {
+ o->fields[o->field_count++] = f;
+ }
+ }
+
+ m->real_oneof_count = m->oneof_count - synthetic_count;
+}
+
+size_t getjsonname(const char *name, char *buf, size_t len) {
+ size_t src, dst = 0;
+ bool ucase_next = false;
+
+#define WRITE(byte) \
+ ++dst; \
+ if (dst < len) buf[dst - 1] = byte; \
+ else if (dst == len) buf[dst - 1] = '\0'
+
+ if (!name) {
+ WRITE('\0');
+ return 0;
+ }
+
+ /* Implement the transformation as described in the spec:
+ * 1. upper case all letters after an underscore.
+ * 2. remove all underscores.
+ */
+ for (src = 0; name[src]; src++) {
+ if (name[src] == '_') {
+ ucase_next = true;
+ continue;
+ }
+
+ if (ucase_next) {
+ WRITE(toupper(name[src]));
+ ucase_next = false;
+ } else {
+ WRITE(name[src]);
+ }
+ }
+
+ WRITE('\0');
+ return dst;
+
+#undef WRITE
+}
+
+static char* makejsonname(symtab_addctx *ctx, const char* name) {
+ size_t size = getjsonname(name, NULL, 0);
+ char* json_name = symtab_alloc(ctx, size);
+ getjsonname(name, json_name, size);
+ return json_name;
+}
+
+static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) {
+ if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) {
+ symtab_errf(ctx, "duplicate symbol '%s'", name);
+ }
+ upb_alloc *alloc = upb_arena_alloc(ctx->symtab->arena);
+ size_t len = strlen(name);
+ CHK_OOM(upb_strtable_insert3(&ctx->symtab->syms, name, len, v, alloc));
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f,
+ const char *base, upb_strview sym,
+ upb_deftype_t type) {
+ const upb_strtable *t = &ctx->symtab->syms;
+ if(sym.size == 0) goto notfound;
+ if(sym.data[0] == '.') {
+ /* Symbols starting with '.' are absolute, so we do a single lookup.
+ * Slice to omit the leading '.' */
+ upb_value v;
+ if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
+ goto notfound;
+ }
+
+ const void *ret = unpack_def(v, type);
+ if (!ret) {
+ symtab_errf(ctx, "type mismatch when resolving field %s, name %s",
+ f->full_name, sym.data);
+ }
+ return ret;
+ } else {
+ /* Remove components from base until we find an entry or run out.
+ * TODO: This branch is totally broken, but currently not used. */
+ (void)base;
+ UPB_ASSERT(false);
+ goto notfound;
+ }
+
+notfound:
+ symtab_errf(ctx, "couldn't resolve name '%s'", sym.data);
+}
+
+static void create_oneofdef(
+ symtab_addctx *ctx, upb_msgdef *m,
+ const google_protobuf_OneofDescriptorProto *oneof_proto) {
+ upb_oneofdef *o;
+ upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+ upb_value v;
+
+ o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
+ o->parent = m;
+ o->full_name = makefullname(ctx, m->full_name, name);
+ o->field_count = 0;
+ o->synthetic = false;
+
+ v = pack_def(o, UPB_DEFTYPE_ONEOF);
+ symtab_add(ctx, o->full_name, v);
+ CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
+
+ CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
+ CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, 4, ctx->alloc));
+}
+
+static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) {
+ str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len);
+ if (!ret) return NULL;
+ ret->len = len;
+ if (len) memcpy(ret->str, data, len);
+ ret->str[len] = '\0';
+ return ret;
+}
+
+static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
+ upb_fielddef *f) {
+ char *end;
+ char nullz[64];
+ errno = 0;
+
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_UINT64:
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_FLOAT:
+ /* Standard C number parsing functions expect null-terminated strings. */
+ if (len >= sizeof(nullz) - 1) {
+ symtab_errf(ctx, "Default too long: %.*s", (int)len, str);
+ }
+ memcpy(nullz, str, len);
+ nullz[len] = '\0';
+ str = nullz;
+ break;
+ default:
+ break;
+ }
+
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT32: {
+ long val = strtol(str, &end, 0);
+ if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.sint = val;
+ break;
+ }
+ case UPB_TYPE_ENUM: {
+ const upb_enumdef *e = f->sub.enumdef;
+ int32_t val;
+ if (!upb_enumdef_ntoi(e, str, len, &val)) {
+ goto invalid;
+ }
+ f->defaultval.sint = val;
+ break;
+ }
+ case UPB_TYPE_INT64: {
+ /* XXX: Need to write our own strtoll, since it's not available in c89. */
+ int64_t val = strtol(str, &end, 0);
+ if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.sint = val;
+ break;
+ }
+ case UPB_TYPE_UINT32: {
+ unsigned long val = strtoul(str, &end, 0);
+ if (val > UINT32_MAX || errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.uint = val;
+ break;
+ }
+ case UPB_TYPE_UINT64: {
+ /* XXX: Need to write our own strtoull, since it's not available in c89. */
+ uint64_t val = strtoul(str, &end, 0);
+ if (val > UINT64_MAX || errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.uint = val;
+ break;
+ }
+ case UPB_TYPE_DOUBLE: {
+ double val = strtod(str, &end);
+ if (errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.dbl = val;
+ break;
+ }
+ case UPB_TYPE_FLOAT: {
+ /* XXX: Need to write our own strtof, since it's not available in c89. */
+ float val = strtod(str, &end);
+ if (errno == ERANGE || *end) {
+ goto invalid;
+ }
+ f->defaultval.flt = val;
+ break;
+ }
+ case UPB_TYPE_BOOL: {
+ if (streql2(str, len, "false")) {
+ f->defaultval.boolean = false;
+ } else if (streql2(str, len, "true")) {
+ f->defaultval.boolean = true;
+ } else {
+ }
+ break;
+ }
+ case UPB_TYPE_STRING:
+ f->defaultval.str = newstr(ctx, str, len);
+ break;
+ case UPB_TYPE_BYTES:
+ /* XXX: need to interpret the C-escaped value. */
+ f->defaultval.str = newstr(ctx, str, len);
+ break;
+ case UPB_TYPE_MESSAGE:
+ /* Should not have a default value. */
+ symtab_errf(ctx, "Message should not have a default (%s)",
+ upb_fielddef_fullname(f));
+ }
+
+ return;
+
+invalid:
+ symtab_errf(ctx, "Invalid default '%.*s' for field %f", (int)len, str,
+ upb_fielddef_fullname(f));
+}
+
+static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_ENUM:
+ f->defaultval.sint = 0;
+ break;
+ case UPB_TYPE_UINT64:
+ case UPB_TYPE_UINT32:
+ f->defaultval.uint = 0;
+ break;
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_FLOAT:
+ f->defaultval.dbl = 0;
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ f->defaultval.str = newstr(ctx, NULL, 0);
+ break;
+ case UPB_TYPE_BOOL:
+ f->defaultval.boolean = false;
+ break;
+ case UPB_TYPE_MESSAGE:
+ break;
+ }
+}
+
+static void create_fielddef(
+ symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
+ const google_protobuf_FieldDescriptorProto *field_proto) {
+ upb_alloc *alloc = ctx->alloc;
+ upb_fielddef *f;
+ const google_protobuf_FieldOptions *options;
+ upb_strview name;
+ const char *full_name;
+ const char *json_name;
+ const char *shortname;
+ uint32_t field_number;
+
+ if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+ symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m));
+ }
+
+ name = google_protobuf_FieldDescriptorProto_name(field_proto);
+ check_ident(ctx, name, false);
+ full_name = makefullname(ctx, prefix, name);
+ shortname = shortdefname(full_name);
+
+ if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
+ json_name = strviewdup(
+ ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
+ } else {
+ json_name = makejsonname(ctx, shortname);
+ }
+
+ field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
+
+ if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
+ symtab_errf(ctx, "invalid field number (%u)", field_number);
+ }
+
+ if (m) {
+ /* direct message field. */
+ upb_value v, field_v, json_v;
+ size_t json_size;
+
+ f = (upb_fielddef*)&m->fields[m->field_count++];
+ f->msgdef = m;
+ f->is_extension_ = false;
+
+ if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
+ symtab_errf(ctx, "duplicate field name (%s)", shortname);
+ }
+
+ if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
+ symtab_errf(ctx, "duplicate json_name (%s)", json_name);
+ }
+
+ if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+ symtab_errf(ctx, "duplicate field number (%u)", field_number);
+ }
+
+ field_v = pack_def(f, UPB_DEFTYPE_FIELD);
+ json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
+ v = upb_value_constptr(f);
+ json_size = strlen(json_name);
+
+ CHK_OOM(
+ upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
+ CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
+
+ if (strcmp(shortname, json_name) != 0) {
+ upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
+ }
+
+ if (ctx->layouts) {
+ const upb_msglayout_field *fields = m->layout->fields;
+ int count = m->layout->field_count;
+ bool found = false;
+ int i;
+ for (i = 0; i < count; i++) {
+ if (fields[i].number == field_number) {
+ f->layout_index = i;
+ found = true;
+ break;
+ }
+ }
+ UPB_ASSERT(found);
+ }
+ } else {
+ /* extension field. */
+ f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
+ f->is_extension_ = true;
+ symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD));
+ }
+
+ f->full_name = full_name;
+ f->json_name = json_name;
+ f->file = ctx->file;
+ f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+ f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+ f->number_ = field_number;
+ f->oneof = NULL;
+ f->proto3_optional_ =
+ google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+
+ /* We can't resolve the subdef or (in the case of extensions) the containing
+ * message yet, because it may not have been defined yet. We stash a pointer
+ * to the field_proto until later when we can properly resolve it. */
+ f->sub.unresolved = field_proto;
+
+ if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
+ symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name);
+ }
+
+ if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+ int oneof_index =
+ google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+ upb_oneofdef *oneof;
+ upb_value v = upb_value_constptr(f);
+
+ if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+ symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+ f->full_name);
+ }
+
+ if (!m) {
+ symtab_errf(ctx, "oneof_index provided for extension field (%s)",
+ f->full_name);
+ }
+
+ if (oneof_index >= m->oneof_count) {
+ symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name);
+ }
+
+ oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
+ f->oneof = oneof;
+
+ oneof->field_count++;
+ if (f->proto3_optional_) {
+ oneof->synthetic = true;
+ }
+ CHK_OOM(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
+ CHK_OOM(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
+ } else {
+ f->oneof = NULL;
+ if (f->proto3_optional_) {
+ symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
+ f->full_name);
+ }
+ }
+
+ options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ?
+ google_protobuf_FieldDescriptorProto_options(field_proto) : NULL;
+
+ if (options && google_protobuf_FieldOptions_has_packed(options)) {
+ f->packed_ = google_protobuf_FieldOptions_packed(options);
+ } else {
+ /* Repeated fields default to packed for proto3 only. */
+ f->packed_ = upb_fielddef_isprimitive(f) &&
+ f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3;
+ }
+
+ if (options) {
+ f->lazy_ = google_protobuf_FieldOptions_lazy(options);
+ } else {
+ f->lazy_ = false;
+ }
+}
+
+static void create_enumdef(
+ symtab_addctx *ctx, const char *prefix,
+ const google_protobuf_EnumDescriptorProto *enum_proto) {
+ upb_enumdef *e;
+ const google_protobuf_EnumValueDescriptorProto *const *values;
+ upb_strview name;
+ size_t i, n;
+
+ name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+ check_ident(ctx, name, false);
+
+ e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
+ e->full_name = makefullname(ctx, prefix, name);
+ symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM));
+
+ values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
+ CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, n, ctx->alloc));
+ CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
+
+ e->file = ctx->file;
+ e->defaultval = 0;
+
+ if (n == 0) {
+ symtab_errf(ctx, "enums must contain at least one value (%s)",
+ e->full_name);
+ }
+
+ for (i = 0; i < n; i++) {
+ const google_protobuf_EnumValueDescriptorProto *value = values[i];
+ upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
+ char *name2 = strviewdup(ctx, name);
+ int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
+ upb_value v = upb_value_int32(num);
+
+ if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
+ symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
+ e->full_name);
+ }
+
+ if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
+ symtab_errf(ctx, "duplicate enum label '%s'", name2);
+ }
+
+ CHK_OOM(name2)
+ CHK_OOM(
+ upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
+
+ if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+ upb_value v = upb_value_cstr(name2);
+ CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
+ }
+ }
+
+ upb_inttable_compact2(&e->iton, ctx->alloc);
+}
+
+static void create_msgdef(symtab_addctx *ctx, const char *prefix,
+ const google_protobuf_DescriptorProto *msg_proto) {
+ upb_msgdef *m;
+ const google_protobuf_MessageOptions *options;
+ const google_protobuf_OneofDescriptorProto *const *oneofs;
+ const google_protobuf_FieldDescriptorProto *const *fields;
+ const google_protobuf_EnumDescriptorProto *const *enums;
+ const google_protobuf_DescriptorProto *const *msgs;
+ size_t i, n_oneof, n_field, n;
+ upb_strview name;
+
+ name = google_protobuf_DescriptorProto_name(msg_proto);
+ check_ident(ctx, name, false);
+
+ m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
+ m->full_name = makefullname(ctx, prefix, name);
+ symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG));
+
+ oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+ fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+
+ CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
+ CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, n_oneof + n_field,
+ ctx->alloc));
+
+ m->file = ctx->file;
+ m->map_entry = false;
+
+ options = google_protobuf_DescriptorProto_options(msg_proto);
+
+ if (options) {
+ m->map_entry = google_protobuf_MessageOptions_map_entry(options);
+ }
+
+ if (ctx->layouts) {
+ m->layout = *ctx->layouts;
+ ctx->layouts++;
+ } else {
+ /* Allocate now (to allow cross-linking), populate later. */
+ m->layout = symtab_alloc(
+ ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry));
+ }
+
+ m->oneof_count = 0;
+ m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
+ for (i = 0; i < n_oneof; i++) {
+ create_oneofdef(ctx, m, oneofs[i]);
+ }
+
+ m->field_count = 0;
+ m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field);
+ for (i = 0; i < n_field; i++) {
+ create_fielddef(ctx, m->full_name, m, fields[i]);
+ }
+
+ assign_msg_indices(ctx, m);
+ finalize_oneofs(ctx, m);
+ assign_msg_wellknowntype(m);
+ upb_inttable_compact2(&m->itof, ctx->alloc);
+
+ /* This message is built. Now build nested messages and enums. */
+
+ enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+ for (i = 0; i < n; i++) {
+ create_enumdef(ctx, m->full_name, enums[i]);
+ }
+
+ msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+ for (i = 0; i < n; i++) {
+ create_msgdef(ctx, m->full_name, msgs[i]);
+ }
+}
+
+static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
+ upb_filedef *file) {
+ const google_protobuf_DescriptorProto *const *msgs;
+ size_t i, n;
+
+ file->msg_count++;
+
+ msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+ for (i = 0; i < n; i++) {
+ count_types_in_msg(msgs[i], file);
+ }
+
+ google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+ file->enum_count += n;
+
+ google_protobuf_DescriptorProto_extension(msg_proto, &n);
+ file->ext_count += n;
+}
+
+static void count_types_in_file(
+ const google_protobuf_FileDescriptorProto *file_proto,
+ upb_filedef *file) {
+ const google_protobuf_DescriptorProto *const *msgs;
+ size_t i, n;
+
+ msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+ for (i = 0; i < n; i++) {
+ count_types_in_msg(msgs[i], file);
+ }
+
+ google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+ file->enum_count += n;
+
+ google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+ file->ext_count += n;
+}
+
+static void resolve_fielddef(symtab_addctx *ctx, const char *prefix,
+ upb_fielddef *f) {
+ upb_strview name;
+ const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
+
+ if (f->is_extension_) {
+ if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+ symtab_errf(ctx, "extension for field '%s' had no extendee",
+ f->full_name);
+ }
+
+ name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+ f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+ }
+
+ if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
+ !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
+ symtab_errf(ctx, "field '%s' is missing type name", f->full_name);
+ }
+
+ name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
+
+ if (upb_fielddef_issubmsg(f)) {
+ f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+ } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
+ f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
+ }
+
+ /* Have to delay resolving of the default value until now because of the enum
+ * case, since enum defaults are specified with a label. */
+ if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
+ upb_strview defaultval =
+ google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+ if (f->file->syntax == UPB_SYNTAX_PROTO3) {
+ symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
+ f->full_name);
+ }
+
+ if (upb_fielddef_issubmsg(f)) {
+ symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
+ f->full_name);
+ }
+
+ parse_default(ctx, defaultval.data, defaultval.size, f);
+ } else {
+ set_default_default(ctx, f);
+ }
+}
+
+static void build_filedef(
+ symtab_addctx *ctx, upb_filedef *file,
+ const google_protobuf_FileDescriptorProto *file_proto) {
+ const google_protobuf_FileOptions *file_options_proto;
+ const google_protobuf_DescriptorProto *const *msgs;
+ const google_protobuf_EnumDescriptorProto *const *enums;
+ const google_protobuf_FieldDescriptorProto *const *exts;
+ const upb_strview* strs;
+ size_t i, n;
+
+ count_types_in_file(file_proto, file);
+
+ file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count);
+ file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count);
+ file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count);
+
+ /* We increment these as defs are added. */
+ file->msg_count = 0;
+ file->enum_count = 0;
+ file->ext_count = 0;
+
+ if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+ symtab_errf(ctx, "File has no name");
+ }
+
+ file->name =
+ strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+ file->phpprefix = NULL;
+ file->phpnamespace = NULL;
+
+ if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
+ upb_strview package =
+ google_protobuf_FileDescriptorProto_package(file_proto);
+ check_ident(ctx, package, true);
+ file->package = strviewdup(ctx, package);
+ } else {
+ file->package = NULL;
+ }
+
+ if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+ upb_strview syntax =
+ google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+ if (streql_view(syntax, "proto2")) {
+ file->syntax = UPB_SYNTAX_PROTO2;
+ } else if (streql_view(syntax, "proto3")) {
+ file->syntax = UPB_SYNTAX_PROTO3;
+ } else {
+ symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
+ UPB_STRVIEW_ARGS(syntax));
+ }
+ } else {
+ file->syntax = UPB_SYNTAX_PROTO2;
+ }
+
+ /* Read options. */
+ file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
+ if (file_options_proto) {
+ if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
+ file->phpprefix = strviewdup(
+ ctx,
+ google_protobuf_FileOptions_php_class_prefix(file_options_proto));
+ }
+ if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
+ file->phpnamespace = strviewdup(
+ ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
+ }
+ }
+
+ /* Verify dependencies. */
+ strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+ file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
+
+ for (i = 0; i < n; i++) {
+ upb_strview dep_name = strs[i];
+ upb_value v;
+ if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
+ dep_name.size, &v)) {
+ symtab_errf(ctx,
+ "Depends on file '" UPB_STRVIEW_FORMAT
+ "', but it has not been loaded",
+ UPB_STRVIEW_ARGS(dep_name));
+ }
+ file->deps[i] = upb_value_getconstptr(v);
+ }
+
+ /* Create messages. */
+ msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+ for (i = 0; i < n; i++) {
+ create_msgdef(ctx, file->package, msgs[i]);
+ }
+
+ /* Create enums. */
+ enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+ for (i = 0; i < n; i++) {
+ create_enumdef(ctx, file->package, enums[i]);
+ }
+
+ /* Create extensions. */
+ exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+ file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n);
+ for (i = 0; i < n; i++) {
+ create_fielddef(ctx, file->package, NULL, exts[i]);
+ }
+
+ /* Now that all names are in the table, build layouts and resolve refs. */
+ for (i = 0; i < (size_t)file->ext_count; i++) {
+ resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]);
+ }
+
+ for (i = 0; i < (size_t)file->msg_count; i++) {
+ const upb_msgdef *m = &file->msgs[i];
+ int j;
+ for (j = 0; j < m->field_count; j++) {
+ resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]);
+ }
+ }
+
+ if (!ctx->layouts) {
+ for (i = 0; i < (size_t)file->msg_count; i++) {
+ const upb_msgdef *m = &file->msgs[i];
+ make_layout(ctx, m);
+ }
+ }
+}
+
+static void remove_filedef(upb_symtab *s, upb_filedef *file) {
+ upb_alloc *alloc = upb_arena_alloc(s->arena);
+ int i;
+ for (i = 0; i < file->msg_count; i++) {
+ const char *name = file->msgs[i].full_name;
+ upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+ }
+ for (i = 0; i < file->enum_count; i++) {
+ const char *name = file->enums[i].full_name;
+ upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+ }
+ for (i = 0; i < file->ext_count; i++) {
+ const char *name = file->exts[i].full_name;
+ upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+ }
+}
+
+static const upb_filedef *_upb_symtab_addfile(
+ upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+ const upb_msglayout **layouts, upb_status *status) {
+ upb_arena *file_arena = upb_arena_new();
+ upb_filedef *file;
+ symtab_addctx ctx;
+
+ if (!file_arena) return NULL;
+
+ file = upb_arena_malloc(file_arena, sizeof(*file));
+ if (!file) goto done;
+
+ ctx.file = file;
+ ctx.symtab = s;
+ ctx.file_arena = file_arena;
+ ctx.alloc = upb_arena_alloc(file_arena);
+ ctx.layouts = layouts;
+ ctx.status = status;
+
+ file->msg_count = 0;
+ file->enum_count = 0;
+ file->ext_count = 0;
+ file->symtab = s;
+
+ if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
+ UPB_ASSERT(!upb_ok(status));
+ remove_filedef(s, file);
+ file = NULL;
+ } else {
+ build_filedef(&ctx, file, file_proto);
+ upb_strtable_insert3(&s->files, file->name, strlen(file->name),
+ upb_value_constptr(file), ctx.alloc);
+ UPB_ASSERT(upb_ok(status));
+ upb_arena_fuse(s->arena, file_arena);
+ }
+
+done:
+ upb_arena_free(file_arena);
+ return file;
+}
+
+const upb_filedef *upb_symtab_addfile(
+ upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+ upb_status *status) {
+ return _upb_symtab_addfile(s, file_proto, NULL, status);
+}
+
+/* Include here since we want most of this file to be stdio-free. */
+#include <stdio.h>
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
+ /* 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_def_init **deps = init->deps;
+ google_protobuf_FileDescriptorProto *file;
+ upb_arena *arena;
+ upb_status status;
+
+ upb_status_clear(&status);
+
+ if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
+ return true;
+ }
+
+ arena = upb_arena_new();
+
+ for (; *deps; deps++) {
+ if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
+ }
+
+ file = google_protobuf_FileDescriptorProto_parse_ex(
+ init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS);
+ s->bytes_loaded += init->descriptor.size;
+
+ if (!file) {
+ upb_status_seterrf(
+ &status,
+ "Failed to parse compiled-in descriptor for file '%s'. This should "
+ "never happen.",
+ init->filename);
+ goto err;
+ }
+
+ if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
+
+ upb_arena_free(arena);
+ return true;
+
+err:
+ fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
+ upb_status_errmsg(&status));
+ upb_arena_free(arena);
+ return false;
+}
+
+size_t _upb_symtab_bytesloaded(const upb_symtab *s) {
+ return s->bytes_loaded;
+}
+
+#undef CHK_OOM
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.h b/contrib/libs/grpc/third_party/upb/upb/def.h
new file mode 100644
index 0000000000..7206ec0d3e
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/def.h
@@ -0,0 +1,315 @@
+/*
+** Defs are upb's internal representation of the constructs that can appear
+** in a .proto file:
+**
+** - upb_msgdef: describes a "message" construct.
+** - upb_fielddef: describes a message field.
+** - upb_filedef: describes a .proto file and its defs.
+** - upb_enumdef: describes an enum.
+** - upb_oneofdef: describes a oneof.
+**
+** TODO: definitions of services.
+*/
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+#include "upb/upb.h"
+#include "upb/table.int.h"
+#include "google/protobuf/descriptor.upb.h"
+
+#include "upb/port_def.inc"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct upb_enumdef;
+typedef struct upb_enumdef upb_enumdef;
+struct upb_fielddef;
+typedef struct upb_fielddef upb_fielddef;
+struct upb_filedef;
+typedef struct upb_filedef upb_filedef;
+struct upb_msgdef;
+typedef struct upb_msgdef upb_msgdef;
+struct upb_oneofdef;
+typedef struct upb_oneofdef upb_oneofdef;
+struct upb_symtab;
+typedef struct upb_symtab upb_symtab;
+
+typedef enum {
+ UPB_SYNTAX_PROTO2 = 2,
+ UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
+/* All the different kind of well known type messages. For simplicity of check,
+ * number wrappers and string wrappers are grouped together. Make sure the
+ * order and merber of these groups are not changed.
+ */
+typedef enum {
+ UPB_WELLKNOWN_UNSPECIFIED,
+ UPB_WELLKNOWN_ANY,
+ UPB_WELLKNOWN_FIELDMASK,
+ UPB_WELLKNOWN_DURATION,
+ UPB_WELLKNOWN_TIMESTAMP,
+ /* number wrappers */
+ UPB_WELLKNOWN_DOUBLEVALUE,
+ UPB_WELLKNOWN_FLOATVALUE,
+ UPB_WELLKNOWN_INT64VALUE,
+ UPB_WELLKNOWN_UINT64VALUE,
+ UPB_WELLKNOWN_INT32VALUE,
+ UPB_WELLKNOWN_UINT32VALUE,
+ /* string wrappers */
+ UPB_WELLKNOWN_STRINGVALUE,
+ UPB_WELLKNOWN_BYTESVALUE,
+ UPB_WELLKNOWN_BOOLVALUE,
+ UPB_WELLKNOWN_VALUE,
+ UPB_WELLKNOWN_LISTVALUE,
+ UPB_WELLKNOWN_STRUCT
+} upb_wellknowntype_t;
+
+/* upb_fielddef ***************************************************************/
+
+/* Maximum field number allowed for FieldDefs. This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+const char *upb_fielddef_jsonname(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
+
+/* Internal only. */
+uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
+
+/* upb_oneofdef ***************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+uint32_t upb_oneofdef_index(const upb_oneofdef *o);
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
+int upb_oneofdef_fieldcount(const upb_oneofdef *o);
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i);
+
+/* Oneof lookups:
+ * - ntof: look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof: look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+ const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+ const char *name) {
+ return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/* DEPRECATED, slated for removal. */
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
+ const upb_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_msgdef *****************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY 1
+#define UPB_MAPENTRY_VALUE 2
+
+/* Well-known field tag numbers for Any messages. */
+#define UPB_ANY_TYPE 1
+#define UPB_ANY_VALUE 2
+
+/* Well-known field tag numbers for timestamp messages. */
+#define UPB_DURATION_SECONDS 1
+#define UPB_DURATION_NANOS 2
+
+/* Well-known field tag numbers for duration messages. */
+#define UPB_TIMESTAMP_SECONDS 1
+#define UPB_TIMESTAMP_NANOS 2
+
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
+const char *upb_msgdef_name(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
+bool upb_msgdef_iswrapper(const upb_msgdef *m);
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
+int upb_msgdef_fieldcount(const upb_msgdef *m);
+int upb_msgdef_oneofcount(const upb_msgdef *m);
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i);
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i);
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+ size_t len);
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+ size_t len);
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+ const char *name) {
+ return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+ const char *name) {
+ return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+/* Internal-only. */
+size_t upb_msgdef_selectorcount(const upb_msgdef *m);
+uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
+
+/* Lookup of either field or oneof by name. Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o);
+
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+ const upb_fielddef **f,
+ const upb_oneofdef **o) {
+ return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
+
+/* Returns a field by either JSON name or regular proto name. */
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+ const char *name, size_t len);
+
+/* DEPRECATED, slated for removal */
+int upb_msgdef_numfields(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+int upb_msgdef_numrealoneofs(const upb_msgdef *m);
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+ const upb_msg_field_iter * iter2);
+void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+ const upb_msg_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_enumdef ****************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
+int32_t upb_enumdef_default(const upb_enumdef *e);
+int upb_enumdef_numvals(const upb_enumdef *e);
+
+/* Enum lookups:
+ * - ntoi: look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton: look up an integer, returning the name as a null-terminated
+ * string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+ int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+ const char *name, int32_t *num) {
+ return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+int upb_filedef_depcount(const upb_filedef *f);
+int upb_filedef_msgcount(const upb_filedef *f);
+int upb_filedef_enumcount(const upb_filedef *f);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
+
+/* upb_symtab *****************************************************************/
+
+upb_symtab *upb_symtab_new(void);
+void upb_symtab_free(upb_symtab* s);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg2(
+ const upb_symtab *s, const char *sym, size_t len);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
+const upb_filedef *upb_symtab_lookupfile2(
+ const upb_symtab *s, const char *name, size_t len);
+int upb_symtab_filecount(const upb_symtab *s);
+const upb_filedef *upb_symtab_addfile(
+ upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
+ upb_status *status);
+size_t _upb_symtab_bytesloaded(const upb_symtab *s);
+
+/* For generated code only: loads a generated descriptor. */
+typedef struct upb_def_init {
+ struct upb_def_init **deps; /* Dependencies of this file. */
+ const upb_msglayout **layouts; /* Pre-order layouts of all messages. */
+ const char *filename;
+ upb_strview descriptor; /* Serialized descriptor. */
+} upb_def_init;
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
+
+#include "upb/port_undef.inc"
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* UPB_DEF_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/def.hpp b/contrib/libs/grpc/third_party/upb/upb/def.hpp
new file mode 100644
index 0000000000..7e304aae7c
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/def.hpp
@@ -0,0 +1,439 @@
+
+#ifndef UPB_DEF_HPP_
+#define UPB_DEF_HPP_
+
+#include <cstring>
+#include <memory>
+#include <util/generic/string.h>
+#include <vector>
+
+#include "upb/def.h"
+#include "upb/upb.hpp"
+
+namespace upb {
+
+class EnumDefPtr;
+class MessageDefPtr;
+class OneofDefPtr;
+
+// A upb::FieldDefPtr describes a single field in a message. It is most often
+// found as a part of a upb_msgdef, but can also stand alone to represent
+// an extension.
+class FieldDefPtr {
+ public:
+ FieldDefPtr() : ptr_(nullptr) {}
+ explicit FieldDefPtr(const upb_fielddef* ptr) : ptr_(ptr) {}
+
+ const upb_fielddef* ptr() const { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ typedef upb_fieldtype_t Type;
+ typedef upb_label_t Label;
+ typedef upb_descriptortype_t DescriptorType;
+
+ const char* full_name() const { return upb_fielddef_fullname(ptr_); }
+
+ Type type() const { return upb_fielddef_type(ptr_); }
+ Label label() const { return upb_fielddef_label(ptr_); }
+ const char* name() const { return upb_fielddef_name(ptr_); }
+ const char* json_name() const { return upb_fielddef_jsonname(ptr_); }
+ uint32_t number() const { return upb_fielddef_number(ptr_); }
+ bool is_extension() const { return upb_fielddef_isextension(ptr_); }
+
+ // For UPB_TYPE_MESSAGE fields only where is_tag_delimited() == false,
+ // indicates whether this field should have lazy parsing handlers that yield
+ // the unparsed string for the submessage.
+ //
+ // TODO(haberman): I think we want to move this into a FieldOptions container
+ // when we add support for custom options (the FieldOptions struct will
+ // contain both regular FieldOptions like "lazy" *and* custom options).
+ bool lazy() const { return upb_fielddef_lazy(ptr_); }
+
+ // For non-string, non-submessage fields, this indicates whether binary
+ // protobufs are encoded in packed or non-packed format.
+ //
+ // TODO(haberman): see note above about putting options like this into a
+ // FieldOptions container.
+ bool packed() const { return upb_fielddef_packed(ptr_); }
+
+ // An integer that can be used as an index into an array of fields for
+ // whatever message this field belongs to. Guaranteed to be less than
+ // f->containing_type()->field_count(). May only be accessed once the def has
+ // been finalized.
+ uint32_t index() const { return upb_fielddef_index(ptr_); }
+
+ // The MessageDef to which this field belongs.
+ //
+ // If this field has been added to a MessageDef, that message can be retrieved
+ // directly (this is always the case for frozen FieldDefs).
+ //
+ // If the field has not yet been added to a MessageDef, you can set the name
+ // of the containing type symbolically instead. This is mostly useful for
+ // extensions, where the extension is declared separately from the message.
+ MessageDefPtr containing_type() const;
+
+ // The OneofDef to which this field belongs, or NULL if this field is not part
+ // of a oneof.
+ OneofDefPtr containing_oneof() const;
+
+ // The field's type according to the enum in descriptor.proto. This is not
+ // the same as UPB_TYPE_*, because it distinguishes between (for example)
+ // INT32 and SINT32, whereas our "type" enum does not. This return of
+ // descriptor_type() is a function of type(), integer_format(), and
+ // is_tag_delimited().
+ DescriptorType descriptor_type() const {
+ return upb_fielddef_descriptortype(ptr_);
+ }
+
+ // Convenient field type tests.
+ bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); }
+ bool IsString() const { return upb_fielddef_isstring(ptr_); }
+ bool IsSequence() const { return upb_fielddef_isseq(ptr_); }
+ bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); }
+ bool IsMap() const { return upb_fielddef_ismap(ptr_); }
+
+ // Returns the non-string default value for this fielddef, which may either
+ // be something the client set explicitly or the "default default" (0 for
+ // numbers, empty for strings). The field's type indicates the type of the
+ // returned value, except for enum fields that are still mutable.
+ //
+ // Requires that the given function matches the field's current type.
+ int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); }
+ int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); }
+ uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); }
+ uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); }
+ bool default_bool() const { return upb_fielddef_defaultbool(ptr_); }
+ float default_float() const { return upb_fielddef_defaultfloat(ptr_); }
+ double default_double() const { return upb_fielddef_defaultdouble(ptr_); }
+
+ // The resulting string is always NULL-terminated. If non-NULL, the length
+ // will be stored in *len.
+ const char* default_string(size_t* len) const {
+ return upb_fielddef_defaultstr(ptr_, len);
+ }
+
+ // Returns the enum or submessage def for this field, if any. The field's
+ // type must match (ie. you may only call enum_subdef() for fields where
+ // type() == UPB_TYPE_ENUM).
+ EnumDefPtr enum_subdef() const;
+ MessageDefPtr message_subdef() const;
+
+ private:
+ const upb_fielddef* ptr_;
+};
+
+// Class that represents a oneof.
+class OneofDefPtr {
+ public:
+ OneofDefPtr() : ptr_(nullptr) {}
+ explicit OneofDefPtr(const upb_oneofdef* ptr) : ptr_(ptr) {}
+
+ const upb_oneofdef* ptr() const { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ // Returns the MessageDef that contains this OneofDef.
+ MessageDefPtr containing_type() const;
+
+ // Returns the name of this oneof.
+ const char* name() const { return upb_oneofdef_name(ptr_); }
+
+ // Returns the number of fields in the oneof.
+ int field_count() const { return upb_oneofdef_numfields(ptr_); }
+ FieldDefPtr field(int i) const { return FieldDefPtr(upb_oneofdef_field(ptr_, i)); }
+
+ // Looks up by name.
+ FieldDefPtr FindFieldByName(const char* name, size_t len) const {
+ return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len));
+ }
+ FieldDefPtr FindFieldByName(const char* name) const {
+ return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name));
+ }
+
+ template <class T>
+ FieldDefPtr FindFieldByName(const T& str) const {
+ return FindFieldByName(str.c_str(), str.size());
+ }
+
+ // Looks up by tag number.
+ FieldDefPtr FindFieldByNumber(uint32_t num) const {
+ return FieldDefPtr(upb_oneofdef_itof(ptr_, num));
+ }
+
+ private:
+ const upb_oneofdef* ptr_;
+};
+
+// Structure that describes a single .proto message type.
+class MessageDefPtr {
+ public:
+ MessageDefPtr() : ptr_(nullptr) {}
+ explicit MessageDefPtr(const upb_msgdef* ptr) : ptr_(ptr) {}
+
+ const upb_msgdef* ptr() const { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ const char* full_name() const { return upb_msgdef_fullname(ptr_); }
+ const char* name() const { return upb_msgdef_name(ptr_); }
+
+ // The number of fields that belong to the MessageDef.
+ int field_count() const { return upb_msgdef_numfields(ptr_); }
+ FieldDefPtr field(int i) const { return FieldDefPtr(upb_msgdef_field(ptr_, i)); }
+
+ // The number of oneofs that belong to the MessageDef.
+ int oneof_count() const { return upb_msgdef_numoneofs(ptr_); }
+ OneofDefPtr oneof(int i) const { return OneofDefPtr(upb_msgdef_oneof(ptr_, i)); }
+
+ upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); }
+
+ // These return null pointers if the field is not found.
+ FieldDefPtr FindFieldByNumber(uint32_t number) const {
+ return FieldDefPtr(upb_msgdef_itof(ptr_, number));
+ }
+ FieldDefPtr FindFieldByName(const char* name, size_t len) const {
+ return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len));
+ }
+ FieldDefPtr FindFieldByName(const char* name) const {
+ return FieldDefPtr(upb_msgdef_ntofz(ptr_, name));
+ }
+
+ template <class T>
+ FieldDefPtr FindFieldByName(const T& str) const {
+ return FindFieldByName(str.c_str(), str.size());
+ }
+
+ OneofDefPtr FindOneofByName(const char* name, size_t len) const {
+ return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len));
+ }
+
+ OneofDefPtr FindOneofByName(const char* name) const {
+ return OneofDefPtr(upb_msgdef_ntooz(ptr_, name));
+ }
+
+ template <class T>
+ OneofDefPtr FindOneofByName(const T& str) const {
+ return FindOneofByName(str.c_str(), str.size());
+ }
+
+ // Is this message a map entry?
+ bool mapentry() const { return upb_msgdef_mapentry(ptr_); }
+
+ // Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for
+ // non-well-known message.
+ upb_wellknowntype_t wellknowntype() const {
+ return upb_msgdef_wellknowntype(ptr_);
+ }
+
+ // Whether is a number wrapper.
+ bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); }
+
+ private:
+ class FieldIter {
+ public:
+ explicit FieldIter(const upb_msgdef *m, int i) : m_(m), i_(i) {}
+ void operator++() { i_++; }
+
+ FieldDefPtr operator*() { return FieldDefPtr(upb_msgdef_field(m_, i_)); }
+ bool operator!=(const FieldIter& other) { return i_ != other.i_; }
+ bool operator==(const FieldIter& other) { return i_ == other.i_; }
+
+ private:
+ const upb_msgdef *m_;
+ int i_;
+ };
+
+ class FieldAccessor {
+ public:
+ explicit FieldAccessor(const upb_msgdef* md) : md_(md) {}
+ FieldIter begin() { return FieldIter(md_, 0); }
+ FieldIter end() { return FieldIter(md_, upb_msgdef_fieldcount(md_)); }
+
+ private:
+ const upb_msgdef* md_;
+ };
+
+ class OneofIter {
+ public:
+ explicit OneofIter(const upb_msgdef *m, int i) : m_(m), i_(i) {}
+ void operator++() { i_++; }
+
+ OneofDefPtr operator*() { return OneofDefPtr(upb_msgdef_oneof(m_, i_)); }
+ bool operator!=(const OneofIter& other) { return i_ != other.i_; }
+ bool operator==(const OneofIter& other) { return i_ == other.i_; }
+
+ private:
+ const upb_msgdef *m_;
+ int i_;
+ };
+
+ class OneofAccessor {
+ public:
+ explicit OneofAccessor(const upb_msgdef* md) : md_(md) {}
+ OneofIter begin() { return OneofIter(md_, 0); }
+ OneofIter end() { return OneofIter(md_, upb_msgdef_oneofcount(md_)); }
+
+ private:
+ const upb_msgdef* md_;
+ };
+
+ public:
+ FieldAccessor fields() const { return FieldAccessor(ptr()); }
+ OneofAccessor oneofs() const { return OneofAccessor(ptr()); }
+
+ private:
+ const upb_msgdef* ptr_;
+};
+
+class EnumDefPtr {
+ public:
+ EnumDefPtr() : ptr_(nullptr) {}
+ explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {}
+
+ const upb_enumdef* ptr() const { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ const char* full_name() const { return upb_enumdef_fullname(ptr_); }
+ const char* name() const { return upb_enumdef_name(ptr_); }
+
+ // The value that is used as the default when no field default is specified.
+ // If not set explicitly, the first value that was added will be used.
+ // The default value must be a member of the enum.
+ // Requires that value_count() > 0.
+ int32_t default_value() const { return upb_enumdef_default(ptr_); }
+
+ // Returns the number of values currently defined in the enum. Note that
+ // multiple names can refer to the same number, so this may be greater than
+ // the total number of unique numbers.
+ int value_count() const { return upb_enumdef_numvals(ptr_); }
+
+ // Lookups from name to integer, returning true if found.
+ bool FindValueByName(const char* name, int32_t* num) const {
+ return upb_enumdef_ntoiz(ptr_, name, num);
+ }
+
+ // Finds the name corresponding to the given number, or NULL if none was
+ // found. If more than one name corresponds to this number, returns the
+ // first one that was added.
+ const char* FindValueByNumber(int32_t num) const {
+ return upb_enumdef_iton(ptr_, num);
+ }
+
+ // Iteration over name/value pairs. The order is undefined.
+ // Adding an enum val invalidates any iterators.
+ //
+ // TODO: make compatible with range-for, with elements as pairs?
+ class Iterator {
+ public:
+ explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); }
+
+ int32_t number() { return upb_enum_iter_number(&iter_); }
+ const char* name() { return upb_enum_iter_name(&iter_); }
+ bool Done() { return upb_enum_done(&iter_); }
+ void Next() { return upb_enum_next(&iter_); }
+
+ private:
+ upb_enum_iter iter_;
+ };
+
+ private:
+ const upb_enumdef* ptr_;
+};
+
+// Class that represents a .proto file with some things defined in it.
+//
+// Many users won't care about FileDefs, but they are necessary if you want to
+// read the values of file-level options.
+class FileDefPtr {
+ public:
+ explicit FileDefPtr(const upb_filedef* ptr) : ptr_(ptr) {}
+
+ const upb_filedef* ptr() const { return ptr_; }
+ explicit operator bool() const { return ptr_ != nullptr; }
+
+ // Get/set name of the file (eg. "foo/bar.proto").
+ const char* name() const { return upb_filedef_name(ptr_); }
+
+ // Package name for definitions inside the file (eg. "foo.bar").
+ const char* package() const { return upb_filedef_package(ptr_); }
+
+ // Sets the php class prefix which is prepended to all php generated classes
+ // from this .proto. Default is empty.
+ const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); }
+
+ // Use this option to change the namespace of php generated classes. Default
+ // is empty. When this option is empty, the package name will be used for
+ // determining the namespace.
+ const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); }
+
+ // Syntax for the file. Defaults to proto2.
+ upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); }
+
+ // Get the list of dependencies from the file. These are returned in the
+ // order that they were added to the FileDefPtr.
+ int dependency_count() const { return upb_filedef_depcount(ptr_); }
+ const FileDefPtr dependency(int index) const {
+ return FileDefPtr(upb_filedef_dep(ptr_, index));
+ }
+
+ private:
+ const upb_filedef* ptr_;
+};
+
+// Non-const methods in upb::SymbolTable are NOT thread-safe.
+class SymbolTable {
+ public:
+ SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {}
+ explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {}
+
+ const upb_symtab* ptr() const { return ptr_.get(); }
+ upb_symtab* ptr() { return ptr_.get(); }
+
+ // Finds an entry in the symbol table with this exact name. If not found,
+ // returns NULL.
+ MessageDefPtr LookupMessage(const char* sym) const {
+ return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym));
+ }
+
+ EnumDefPtr LookupEnum(const char* sym) const {
+ return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym));
+ }
+
+ FileDefPtr LookupFile(const char* name) const {
+ return FileDefPtr(upb_symtab_lookupfile(ptr_.get(), name));
+ }
+
+ // TODO: iteration?
+
+ // Adds the given serialized FileDescriptorProto to the pool.
+ FileDefPtr AddFile(const google_protobuf_FileDescriptorProto* file_proto,
+ Status* status) {
+ return FileDefPtr(
+ upb_symtab_addfile(ptr_.get(), file_proto, status->ptr()));
+ }
+
+ private:
+ std::unique_ptr<upb_symtab, decltype(&upb_symtab_free)> ptr_;
+};
+
+inline MessageDefPtr FieldDefPtr::message_subdef() const {
+ return MessageDefPtr(upb_fielddef_msgsubdef(ptr_));
+}
+
+inline MessageDefPtr FieldDefPtr::containing_type() const {
+ return MessageDefPtr(upb_fielddef_containingtype(ptr_));
+}
+
+inline MessageDefPtr OneofDefPtr::containing_type() const {
+ return MessageDefPtr(upb_oneofdef_containingtype(ptr_));
+}
+
+inline OneofDefPtr FieldDefPtr::containing_oneof() const {
+ return OneofDefPtr(upb_fielddef_containingoneof(ptr_));
+}
+
+inline EnumDefPtr FieldDefPtr::enum_subdef() const {
+ return EnumDefPtr(upb_fielddef_enumsubdef(ptr_));
+}
+
+} // namespace upb
+
+#endif // UPB_DEF_HPP_
diff --git a/contrib/libs/grpc/third_party/upb/upb/encode.c b/contrib/libs/grpc/third_party/upb/upb/encode.c
index a6ce62bfa5..f73ff09f8e 100644
--- a/contrib/libs/grpc/third_party/upb/upb/encode.c
+++ b/contrib/libs/grpc/third_party/upb/upb/encode.c
@@ -2,35 +2,39 @@
#include "upb/encode.h"
+#include <setjmp.h>
#include <string.h>
#include "upb/msg.h"
#include "upb/upb.h"
+/* Must be last. */
#include "upb/port_def.inc"
#define UPB_PB_VARINT_MAX_LEN 10
-#define CHK(x) do { if (!(x)) { return false; } } while(0)
-static size_t upb_encode_varint(uint64_t val, char *buf) {
- size_t i;
- if (val < 128) { buf[0] = val; return 1; }
- i = 0;
- while (val) {
+UPB_NOINLINE
+static size_t encode_varint64(uint64_t val, char *buf) {
+ size_t i = 0;
+ do {
uint8_t byte = val & 0x7fU;
val >>= 7;
if (val) byte |= 0x80U;
buf[i++] = byte;
- }
+ } while (val);
return i;
}
-static uint32_t upb_zzencode_32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
-static uint64_t upb_zzencode_64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
+static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
+static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
typedef struct {
+ jmp_buf err;
upb_alloc *alloc;
char *buf, *ptr, *limit;
+ int options;
+ int depth;
+ _upb_mapsorter sorter;
} upb_encstate;
static size_t upb_roundup_pow2(size_t bytes) {
@@ -41,11 +45,17 @@ static size_t upb_roundup_pow2(size_t bytes) {
return ret;
}
-static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
+UPB_NORETURN static void encode_err(upb_encstate *e) {
+ UPB_LONGJMP(e->err, 1);
+}
+
+UPB_NOINLINE
+static void encode_growbuffer(upb_encstate *e, size_t bytes) {
size_t old_size = e->limit - e->buf;
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);
- CHK(new_buf);
+
+ if (!new_buf) encode_err(e);
/* We want previous data at the end, realloc() put it at the beginning. */
if (old_size > 0) {
@@ -55,99 +65,116 @@ static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
e->ptr = new_buf + new_size - (e->limit - e->ptr);
e->limit = new_buf + new_size;
e->buf = new_buf;
- return true;
+
+ e->ptr -= bytes;
}
/* Call to ensure that at least "bytes" bytes are available for writing at
* e->ptr. Returns false if the bytes could not be allocated. */
-static bool upb_encode_reserve(upb_encstate *e, size_t bytes) {
- CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) ||
- upb_encode_growbuffer(e, bytes));
+UPB_FORCEINLINE
+static void encode_reserve(upb_encstate *e, size_t bytes) {
+ if ((size_t)(e->ptr - e->buf) < bytes) {
+ encode_growbuffer(e, bytes);
+ return;
+ }
e->ptr -= bytes;
- return true;
}
/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) {
- if (len == 0) return true;
- CHK(upb_encode_reserve(e, len));
+static void encode_bytes(upb_encstate *e, const void *data, size_t len) {
+ if (len == 0) return; /* memcpy() with zero size is UB */
+ encode_reserve(e, len);
memcpy(e->ptr, data, len);
- return true;
}
-static bool upb_put_fixed64(upb_encstate *e, uint64_t val) {
+static void encode_fixed64(upb_encstate *e, uint64_t val) {
val = _upb_be_swap64(val);
- return upb_put_bytes(e, &val, sizeof(uint64_t));
+ encode_bytes(e, &val, sizeof(uint64_t));
}
-static bool upb_put_fixed32(upb_encstate *e, uint32_t val) {
+static void encode_fixed32(upb_encstate *e, uint32_t val) {
val = _upb_be_swap32(val);
- return upb_put_bytes(e, &val, sizeof(uint32_t));
+ encode_bytes(e, &val, sizeof(uint32_t));
}
-static bool upb_put_varint(upb_encstate *e, uint64_t val) {
+UPB_NOINLINE
+static void encode_longvarint(upb_encstate *e, uint64_t val) {
size_t len;
char *start;
- CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN));
- len = upb_encode_varint(val, e->ptr);
+
+ encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
+ len = encode_varint64(val, e->ptr);
start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
memmove(start, e->ptr, len);
e->ptr = start;
- return true;
}
-static bool upb_put_double(upb_encstate *e, double d) {
+UPB_FORCEINLINE
+static void encode_varint(upb_encstate *e, uint64_t val) {
+ if (val < 128 && e->ptr != e->buf) {
+ --e->ptr;
+ *e->ptr = val;
+ } else {
+ encode_longvarint(e, val);
+ }
+}
+
+static void encode_double(upb_encstate *e, double d) {
uint64_t u64;
UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
memcpy(&u64, &d, sizeof(uint64_t));
- return upb_put_fixed64(e, u64);
+ encode_fixed64(e, u64);
}
-static bool upb_put_float(upb_encstate *e, float d) {
+static void encode_float(upb_encstate *e, float d) {
uint32_t u32;
UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
memcpy(&u32, &d, sizeof(uint32_t));
- return upb_put_fixed32(e, u32);
+ encode_fixed32(e, u32);
}
-static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
- return upb_put_varint(e, (field_number << 3) | wire_type);
+static void encode_tag(upb_encstate *e, uint32_t field_number,
+ uint8_t wire_type) {
+ encode_varint(e, (field_number << 3) | wire_type);
}
-static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
+static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
size_t elem_size, uint32_t tag) {
size_t bytes = arr->len * elem_size;
const char* data = _upb_array_constptr(arr);
const char* ptr = data + bytes - elem_size;
if (tag) {
while (true) {
- CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag));
+ encode_bytes(e, ptr, elem_size);
+ encode_varint(e, tag);
if (ptr == data) break;
ptr -= elem_size;
}
- return true;
} else {
- return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes);
+ encode_bytes(e, data, bytes);
}
}
-bool upb_encode_message(upb_encstate *e, const char *msg,
- const upb_msglayout *m, size_t *size);
+static void encode_message(upb_encstate *e, const char *msg,
+ const upb_msglayout *m, size_t *size);
-static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f,
- bool skip_zero_value) {
+static void encode_scalar(upb_encstate *e, const void *_field_mem,
+ const upb_msglayout *m, const upb_msglayout_field *f,
+ bool skip_zero_value) {
const char *field_mem = _field_mem;
-#define CASE(ctype, type, wire_type, encodeval) do { \
- ctype val = *(ctype*)field_mem; \
- if (skip_zero_value && val == 0) { \
- return true; \
- } \
- return upb_put_ ## type(e, encodeval) && \
- upb_put_tag(e, f->number, wire_type); \
-} while(0)
+ int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+ { \
+ ctype val = *(ctype *)field_mem; \
+ if (skip_zero_value && val == 0) { \
+ return; \
+ } \
+ encode_##type(e, encodeval); \
+ wire_type = wtype; \
+ break; \
+ }
switch (f->descriptortype) {
case UPB_DESCRIPTOR_TYPE_DOUBLE:
@@ -171,90 +198,95 @@ static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem,
case UPB_DESCRIPTOR_TYPE_BOOL:
CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
case UPB_DESCRIPTOR_TYPE_SINT32:
- CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val));
+ CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val));
case UPB_DESCRIPTOR_TYPE_SINT64:
- CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val));
+ CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val));
case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: {
upb_strview view = *(upb_strview*)field_mem;
if (skip_zero_value && view.size == 0) {
- return true;
+ return;
}
- return upb_put_bytes(e, view.data, view.size) &&
- upb_put_varint(e, view.size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+ encode_bytes(e, view.data, view.size);
+ encode_varint(e, view.size);
+ wire_type = UPB_WIRE_TYPE_DELIMITED;
+ break;
}
case UPB_DESCRIPTOR_TYPE_GROUP: {
size_t size;
void *submsg = *(void **)field_mem;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (submsg == NULL) {
- return true;
+ return;
}
- return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
- upb_encode_message(e, submsg, subm, &size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
+ if (--e->depth == 0) encode_err(e);
+ encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+ encode_message(e, submsg, subm, &size);
+ wire_type = UPB_WIRE_TYPE_START_GROUP;
+ e->depth++;
+ break;
}
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
size_t size;
void *submsg = *(void **)field_mem;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (submsg == NULL) {
- return true;
+ return;
}
- return upb_encode_message(e, submsg, subm, &size) &&
- upb_put_varint(e, size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+ if (--e->depth == 0) encode_err(e);
+ encode_message(e, submsg, subm, &size);
+ encode_varint(e, size);
+ wire_type = UPB_WIRE_TYPE_DELIMITED;
+ e->depth++;
+ break;
}
+ default:
+ UPB_UNREACHABLE();
}
#undef CASE
- UPB_UNREACHABLE();
+
+ encode_tag(e, f->number, wire_type);
}
-static bool upb_encode_array(upb_encstate *e, const char *field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f) {
+static void encode_array(upb_encstate *e, const char *field_mem,
+ const upb_msglayout *m, const upb_msglayout_field *f) {
const upb_array *arr = *(const upb_array**)field_mem;
bool packed = f->label == _UPB_LABEL_PACKED;
+ size_t pre_len = e->limit - e->ptr;
if (arr == NULL || arr->len == 0) {
- return true;
+ return;
}
#define VARINT_CASE(ctype, encode) \
{ \
const ctype *start = _upb_array_constptr(arr); \
const ctype *ptr = start + arr->len; \
- size_t pre_len = e->limit - e->ptr; \
uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
do { \
ptr--; \
- CHK(upb_put_varint(e, encode)); \
- if (tag) CHK(upb_put_varint(e, tag)); \
+ encode_varint(e, encode); \
+ if (tag) encode_varint(e, tag); \
} while (ptr != start); \
- if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len)); \
} \
- break; \
- do { \
- ; \
- } while (0)
+ break;
#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
switch (f->descriptortype) {
case UPB_DESCRIPTOR_TYPE_DOUBLE:
- CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)));
+ encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT));
break;
case UPB_DESCRIPTOR_TYPE_FLOAT:
- CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)));
+ encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT));
break;
case UPB_DESCRIPTOR_TYPE_SFIXED64:
case UPB_DESCRIPTOR_TYPE_FIXED64:
- CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)));
+ encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT));
break;
case UPB_DESCRIPTOR_TYPE_FIXED32:
case UPB_DESCRIPTOR_TYPE_SFIXED32:
- CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)));
+ encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT));
break;
case UPB_DESCRIPTOR_TYPE_INT64:
case UPB_DESCRIPTOR_TYPE_UINT64:
@@ -267,154 +299,180 @@ static bool upb_encode_array(upb_encstate *e, const char *field_mem,
case UPB_DESCRIPTOR_TYPE_BOOL:
VARINT_CASE(bool, *ptr);
case UPB_DESCRIPTOR_TYPE_SINT32:
- VARINT_CASE(int32_t, upb_zzencode_32(*ptr));
+ VARINT_CASE(int32_t, encode_zz32(*ptr));
case UPB_DESCRIPTOR_TYPE_SINT64:
- VARINT_CASE(int64_t, upb_zzencode_64(*ptr));
+ VARINT_CASE(int64_t, encode_zz64(*ptr));
case UPB_DESCRIPTOR_TYPE_STRING:
case UPB_DESCRIPTOR_TYPE_BYTES: {
const upb_strview *start = _upb_array_constptr(arr);
const upb_strview *ptr = start + arr->len;
do {
ptr--;
- CHK(upb_put_bytes(e, ptr->data, ptr->size) &&
- upb_put_varint(e, ptr->size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
+ encode_bytes(e, ptr->data, ptr->size);
+ encode_varint(e, ptr->size);
+ encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
} while (ptr != start);
- return true;
+ return;
}
case UPB_DESCRIPTOR_TYPE_GROUP: {
const void *const*start = _upb_array_constptr(arr);
const void *const*ptr = start + arr->len;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
+ if (--e->depth == 0) encode_err(e);
do {
size_t size;
ptr--;
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
- upb_encode_message(e, *ptr, subm, &size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP));
+ encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+ encode_message(e, *ptr, subm, &size);
+ encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
} while (ptr != start);
- return true;
+ e->depth++;
+ return;
}
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
const void *const*start = _upb_array_constptr(arr);
const void *const*ptr = start + arr->len;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
+ if (--e->depth == 0) encode_err(e);
do {
size_t size;
ptr--;
- CHK(upb_encode_message(e, *ptr, subm, &size) &&
- upb_put_varint(e, size) &&
- upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
+ encode_message(e, *ptr, subm, &size);
+ encode_varint(e, size);
+ encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
} while (ptr != start);
- return true;
+ e->depth++;
+ return;
}
}
#undef VARINT_CASE
if (packed) {
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
+ encode_varint(e, e->limit - e->ptr - pre_len);
+ encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
}
- return true;
}
-static bool upb_encode_map(upb_encstate *e, const char *field_mem,
- const upb_msglayout *m,
- const upb_msglayout_field *f) {
+static void encode_mapentry(upb_encstate *e, uint32_t number,
+ const upb_msglayout *layout,
+ const upb_map_entry *ent) {
+ const upb_msglayout_field *key_field = &layout->fields[0];
+ const upb_msglayout_field *val_field = &layout->fields[1];
+ size_t pre_len = e->limit - e->ptr;
+ size_t size;
+ encode_scalar(e, &ent->v, layout, val_field, false);
+ encode_scalar(e, &ent->k, layout, key_field, false);
+ size = (e->limit - e->ptr) - pre_len;
+ encode_varint(e, size);
+ encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
+}
+
+static void encode_map(upb_encstate *e, const char *field_mem,
+ const upb_msglayout *m, const upb_msglayout_field *f) {
const upb_map *map = *(const upb_map**)field_mem;
- const upb_msglayout *entry = m->submsgs[f->submsg_index];
- const upb_msglayout_field *key_field = &entry->fields[0];
- const upb_msglayout_field *val_field = &entry->fields[1];
- upb_strtable_iter i;
- if (map == NULL) {
- return true;
- }
+ const upb_msglayout *layout = m->submsgs[f->submsg_index];
+ UPB_ASSERT(layout->field_count == 2);
+
+ if (map == NULL) return;
- upb_strtable_begin(&i, &map->table);
- for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- size_t pre_len = e->limit - e->ptr;
- size_t size;
- upb_strview key = upb_strtable_iter_key(&i);
- const upb_value val = upb_strtable_iter_value(&i);
+ if (e->options & UPB_ENCODE_DETERMINISTIC) {
+ _upb_sortedmap sorted;
+ _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+ &sorted);
upb_map_entry ent;
- _upb_map_fromkey(key, &ent.k, map->key_size);
- _upb_map_fromvalue(val, &ent.v, map->val_size);
- CHK(upb_encode_scalarfield(e, &ent.v, entry, val_field, false));
- CHK(upb_encode_scalarfield(e, &ent.k, entry, key_field, false));
- size = (e->limit - e->ptr) - pre_len;
- CHK(upb_put_varint(e, size));
- CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
+ while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+ encode_mapentry(e, f->number, layout, &ent);
+ }
+ _upb_mapsorter_popmap(&e->sorter, &sorted);
+ } else {
+ upb_strtable_iter i;
+ upb_strtable_begin(&i, &map->table);
+ for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ upb_strview key = upb_strtable_iter_key(&i);
+ const upb_value val = upb_strtable_iter_value(&i);
+ upb_map_entry ent;
+ _upb_map_fromkey(key, &ent.k, map->key_size);
+ _upb_map_fromvalue(val, &ent.v, map->val_size);
+ encode_mapentry(e, f->number, layout, &ent);
+ }
}
-
- return true;
}
+static void encode_scalarfield(upb_encstate *e, const char *msg,
+ const upb_msglayout *m,
+ const upb_msglayout_field *f) {
+ bool skip_empty = false;
+ if (f->presence == 0) {
+ /* Proto3 presence. */
+ skip_empty = true;
+ } else if (f->presence > 0) {
+ /* Proto2 presence: hasbit. */
+ if (!_upb_hasbit_field(msg, f)) return;
+ } else {
+ /* Field is in a oneof. */
+ if (_upb_getoneofcase_field(msg, f) != f->number) return;
+ }
+ encode_scalar(e, msg + f->offset, m, f, skip_empty);
+}
-bool upb_encode_message(upb_encstate *e, const char *msg,
- const upb_msglayout *m, size_t *size) {
- int i;
+static void encode_message(upb_encstate *e, const char *msg,
+ const upb_msglayout *m, size_t *size) {
size_t pre_len = e->limit - e->ptr;
- const char *unknown;
- size_t unknown_size;
+ const upb_msglayout_field *f = &m->fields[m->field_count];
+ const upb_msglayout_field *first = &m->fields[0];
- unknown = upb_msg_getunknown(msg, &unknown_size);
+ if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
+ size_t unknown_size;
+ const char *unknown = upb_msg_getunknown(msg, &unknown_size);
- if (unknown) {
- upb_put_bytes(e, unknown, unknown_size);
+ if (unknown) {
+ encode_bytes(e, unknown, unknown_size);
+ }
}
- for (i = m->field_count - 1; i >= 0; i--) {
- const upb_msglayout_field *f = &m->fields[i];
-
+ while (f != first) {
+ f--;
if (_upb_isrepeated(f)) {
- CHK(upb_encode_array(e, msg + f->offset, m, f));
+ encode_array(e, msg + f->offset, m, f);
} else if (f->label == _UPB_LABEL_MAP) {
- CHK(upb_encode_map(e, msg + f->offset, m, f));
+ encode_map(e, msg + f->offset, m, f);
} else {
- bool skip_empty = false;
- if (f->presence == 0) {
- /* Proto3 presence. */
- skip_empty = true;
- } else if (f->presence > 0) {
- /* Proto2 presence: hasbit. */
- if (!_upb_hasbit_field(msg, f)) {
- continue;
- }
- } else {
- /* Field is in a oneof. */
- if (_upb_getoneofcase_field(msg, f) != f->number) {
- continue;
- }
- }
- CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
+ encode_scalarfield(e, msg, m, f);
}
}
*size = (e->limit - e->ptr) - pre_len;
- return true;
}
-char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena,
- size_t *size) {
+char *upb_encode_ex(const void *msg, const upb_msglayout *m, int options,
+ upb_arena *arena, size_t *size) {
upb_encstate e;
+ unsigned depth = (unsigned)options >> 16;
+
e.alloc = upb_arena_alloc(arena);
e.buf = NULL;
e.limit = NULL;
e.ptr = NULL;
+ e.depth = depth ? depth : 64;
+ e.options = options;
+ _upb_mapsorter_init(&e.sorter);
+ char *ret = NULL;
- if (!upb_encode_message(&e, msg, m, size)) {
+ if (UPB_SETJMP(e.err)) {
*size = 0;
- return NULL;
- }
-
- *size = e.limit - e.ptr;
-
- if (*size == 0) {
- static char ch;
- return &ch;
+ ret = NULL;
} else {
- UPB_ASSERT(e.ptr);
- return e.ptr;
+ encode_message(&e, msg, m, size);
+ *size = e.limit - e.ptr;
+ if (*size == 0) {
+ static char ch;
+ ret = &ch;
+ } else {
+ UPB_ASSERT(e.ptr);
+ ret = e.ptr;
+ }
}
-}
-#undef CHK
+ _upb_mapsorter_destroy(&e.sorter);
+ return ret;
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/encode.h b/contrib/libs/grpc/third_party/upb/upb/encode.h
index 6842777058..d3c1dc9606 100644
--- a/contrib/libs/grpc/third_party/upb/upb/encode.h
+++ b/contrib/libs/grpc/third_party/upb/upb/encode.h
@@ -7,12 +7,37 @@
#include "upb/msg.h"
+/* Must be last. */
+#include "upb/port_def.inc"
+
#ifdef __cplusplus
extern "C" {
#endif
-char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
- size_t *size);
+enum {
+ /* If set, the results of serializing will be deterministic across all
+ * instances of this binary. There are no guarantees across different
+ * binary builds.
+ *
+ * If your proto contains maps, the encoder will need to malloc()/free()
+ * memory during encode. */
+ UPB_ENCODE_DETERMINISTIC = 1,
+
+ /* When set, unknown fields are not printed. */
+ UPB_ENCODE_SKIPUNKNOWN = 2,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+ upb_arena *arena, size_t *size);
+
+UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l,
+ upb_arena *arena, size_t *size) {
+ return upb_encode_ex(msg, l, 0, arena, size);
+}
+
+#include "upb/port_undef.inc"
#ifdef __cplusplus
} /* extern "C" */
diff --git a/contrib/libs/grpc/third_party/upb/upb/msg.c b/contrib/libs/grpc/third_party/upb/upb/msg.c
index 25747c8481..876a06d6fa 100644
--- a/contrib/libs/grpc/third_party/upb/upb/msg.c
+++ b/contrib/libs/grpc/third_party/upb/upb/msg.c
@@ -7,106 +7,67 @@
/** upb_msg *******************************************************************/
-static const char _upb_fieldtype_to_sizelg2[12] = {
- 0,
- 0, /* UPB_TYPE_BOOL */
- 2, /* UPB_TYPE_FLOAT */
- 2, /* UPB_TYPE_INT32 */
- 2, /* UPB_TYPE_UINT32 */
- 2, /* UPB_TYPE_ENUM */
- UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */
- 3, /* UPB_TYPE_DOUBLE */
- 3, /* UPB_TYPE_INT64 */
- 3, /* UPB_TYPE_UINT64 */
- UPB_SIZE(3, 4), /* UPB_TYPE_STRING */
- UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */
-};
-
-static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) {
- UPB_ASSERT(elem_size_lg2 <= 4);
- return (uintptr_t)ptr | elem_size_lg2;
-}
-
-static int upb_msg_internalsize(const upb_msglayout *l) {
- return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
- return l->size + upb_msg_internalsize(l);
-}
+static const size_t overhead = sizeof(upb_msg_internal);
static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
ptrdiff_t size = sizeof(upb_msg_internal);
- return UPB_PTR_AT(msg, -size, upb_msg_internal);
+ return (upb_msg_internal*)((char*)msg - size);
}
-static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
- return (upb_msg_internal*)upb_msg_getinternal_const(msg);
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
+ return _upb_msg_new_inl(l, a);
}
void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) {
- ptrdiff_t internal = upb_msg_internalsize(l);
- void *mem = UPB_PTR_AT(msg, -internal, char);
- memset(mem, 0, l->size + internal);
-}
-
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
- void *mem = upb_arena_malloc(a, upb_msg_sizeof(l));
- upb_msg *msg;
-
- if (!mem) {
- return NULL;
- }
-
- msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg);
- _upb_msg_clear(msg, l);
- return msg;
+ void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char);
+ memset(mem, 0, upb_msg_sizeof(l));
}
bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
upb_arena *arena) {
+
upb_msg_internal *in = upb_msg_getinternal(msg);
- if (len > in->unknown_size - in->unknown_len) {
- upb_alloc *alloc = upb_arena_alloc(arena);
- size_t need = in->unknown_size + len;
- size_t newsize = UPB_MAX(in->unknown_size * 2, need);
- void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
- if (!mem) return false;
- in->unknown = mem;
- in->unknown_size = newsize;
+ if (!in->unknown) {
+ size_t size = 128;
+ while (size < len) size *= 2;
+ in->unknown = upb_arena_malloc(arena, size + overhead);
+ if (!in->unknown) return false;
+ in->unknown->size = size;
+ in->unknown->len = 0;
+ } else if (in->unknown->size - in->unknown->len < len) {
+ size_t need = in->unknown->len + len;
+ size_t size = in->unknown->size;
+ while (size < need) size *= 2;
+ in->unknown = upb_arena_realloc(
+ arena, in->unknown, in->unknown->size + overhead, size + overhead);
+ if (!in->unknown) return false;
+ in->unknown->size = size;
}
- memcpy(in->unknown + in->unknown_len, data, len);
- in->unknown_len += len;
+ memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len);
+ in->unknown->len += len;
return true;
}
void _upb_msg_discardunknown_shallow(upb_msg *msg) {
upb_msg_internal *in = upb_msg_getinternal(msg);
- in->unknown_len = 0;
+ if (in->unknown) {
+ in->unknown->len = 0;
+ }
}
const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
const upb_msg_internal *in = upb_msg_getinternal_const(msg);
- *len = in->unknown_len;
- return in->unknown;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) {
- upb_array *arr = upb_arena_malloc(a, sizeof(upb_array));
-
- if (!arr) {
+ if (in->unknown) {
+ *len = in->unknown->len;
+ return (char*)(in->unknown + 1);
+ } else {
+ *len = 0;
return NULL;
}
-
- arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]);
- arr->len = 0;
- arr->size = 0;
-
- return arr;
}
+/** upb_array *****************************************************************/
+
bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
size_t new_size = UPB_MAX(arr->size, 4);
int elem_size_lg2 = arr->data & 7;
@@ -124,16 +85,16 @@ bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
return false;
}
- arr->data = tag_arrptr(ptr, elem_size_lg2);
+ arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
arr->size = new_size;
return true;
}
-static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
+static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2,
upb_arena *arena) {
upb_array *arr = *arr_ptr;
if (!arr) {
- arr = _upb_array_new(arena, type);
+ arr = _upb_array_new(arena, 4, elem_size_lg2);
if (!arr) return NULL;
*arr_ptr = arr;
}
@@ -141,22 +102,25 @@ static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
}
void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
- upb_fieldtype_t type, upb_arena *arena) {
- upb_array *arr = getorcreate_array(arr_ptr, type, arena);
- return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr) : NULL;
+ int elem_size_lg2, upb_arena *arena) {
+ upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+ return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr)
+ : NULL;
}
bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
- upb_fieldtype_t type, upb_arena *arena) {
- upb_array *arr = getorcreate_array(arr_ptr, type, arena);
- size_t elem = arr->len;
- int lg2 = _upb_fieldtype_to_sizelg2[type];
- char *data;
+ int elem_size_lg2, upb_arena *arena) {
+ upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+ if (!arr) return false;
+
+ size_t elems = arr->len;
- if (!arr || !_upb_array_resize(arr, elem + 1, arena)) return false;
+ if (!_upb_array_resize(arr, elems + 1, arena)) {
+ return false;
+ }
- data = _upb_array_ptr(arr);
- memcpy(data + (elem << lg2), value, 1 << lg2);
+ char *data = _upb_array_ptr(arr);
+ memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2);
return true;
}
@@ -169,9 +133,124 @@ upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
return NULL;
}
- upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a));
+ upb_strtable_init2(&map->table, UPB_CTYPE_INT32, 4, upb_arena_alloc(a));
map->key_size = key_size;
map->val_size = value_size;
return map;
}
+
+static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key,
+ void *b_key, size_t size) {
+ const upb_tabent *const*a = _a;
+ const upb_tabent *const*b = _b;
+ upb_strview a_tabkey = upb_tabstrview((*a)->key);
+ upb_strview b_tabkey = upb_tabstrview((*b)->key);
+ _upb_map_fromkey(a_tabkey, a_key, size);
+ _upb_map_fromkey(b_tabkey, b_key, size);
+}
+
+static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) {
+ int64_t a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+ return a - b;
+}
+
+static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) {
+ uint64_t a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+ return a - b;
+}
+
+static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) {
+ int32_t a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+ return a - b;
+}
+
+static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) {
+ uint32_t a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+ return a - b;
+}
+
+static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) {
+ bool a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
+ return a - b;
+}
+
+static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) {
+ upb_strview a, b;
+ _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
+ size_t common_size = UPB_MIN(a.size, b.size);
+ int cmp = memcmp(a.data, b.data, common_size);
+ if (cmp) return cmp;
+ return a.size - b.size;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+ const upb_map *map, _upb_sortedmap *sorted) {
+ int map_size = _upb_map_size(map);
+ sorted->start = s->size;
+ sorted->pos = sorted->start;
+ sorted->end = sorted->start + map_size;
+
+ /* Grow s->entries if necessary. */
+ if (sorted->end > s->cap) {
+ s->cap = _upb_lg2ceilsize(sorted->end);
+ s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
+ if (!s->entries) return false;
+ }
+
+ s->size = sorted->end;
+
+ /* Copy non-empty entries from the table to s->entries. */
+ upb_tabent const**dst = &s->entries[sorted->start];
+ const upb_tabent *src = map->table.t.entries;
+ const upb_tabent *end = src + upb_table_size(&map->table.t);
+ for (; src < end; src++) {
+ if (!upb_tabent_isempty(src)) {
+ *dst = src;
+ dst++;
+ }
+ }
+ UPB_ASSERT(dst == &s->entries[sorted->end]);
+
+ /* Sort entries according to the key type. */
+
+ int (*compar)(const void *, const void *);
+
+ switch (key_type) {
+ case UPB_DESCRIPTOR_TYPE_INT64:
+ case UPB_DESCRIPTOR_TYPE_SFIXED64:
+ case UPB_DESCRIPTOR_TYPE_SINT64:
+ compar = _upb_mapsorter_cmpi64;
+ break;
+ case UPB_DESCRIPTOR_TYPE_UINT64:
+ case UPB_DESCRIPTOR_TYPE_FIXED64:
+ compar = _upb_mapsorter_cmpu64;
+ break;
+ case UPB_DESCRIPTOR_TYPE_INT32:
+ case UPB_DESCRIPTOR_TYPE_SINT32:
+ case UPB_DESCRIPTOR_TYPE_SFIXED32:
+ case UPB_DESCRIPTOR_TYPE_ENUM:
+ compar = _upb_mapsorter_cmpi32;
+ break;
+ case UPB_DESCRIPTOR_TYPE_UINT32:
+ case UPB_DESCRIPTOR_TYPE_FIXED32:
+ compar = _upb_mapsorter_cmpu32;
+ break;
+ case UPB_DESCRIPTOR_TYPE_BOOL:
+ compar = _upb_mapsorter_cmpbool;
+ break;
+ case UPB_DESCRIPTOR_TYPE_STRING:
+ compar = _upb_mapsorter_cmpstr;
+ break;
+ default:
+ UPB_UNREACHABLE();
+ }
+
+ qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+ return true;
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/msg.h b/contrib/libs/grpc/third_party/upb/upb/msg.h
index 695c278b21..9b4557ac18 100644
--- a/contrib/libs/grpc/third_party/upb/upb/msg.h
+++ b/contrib/libs/grpc/third_party/upb/upb/msg.h
@@ -9,11 +9,13 @@
#define UPB_MSG_H_
#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
#include "upb/table.int.h"
#include "upb/upb.h"
+/* Must be last. */
#include "upb/port_def.inc"
#ifdef __cplusplus
@@ -46,6 +48,18 @@ typedef struct {
uint8_t label; /* google.protobuf.Label or _UPB_LABEL_* above. */
} upb_msglayout_field;
+struct upb_decstate;
+struct upb_msglayout;
+
+typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
+ upb_msg *msg, intptr_t table,
+ uint64_t hasbits, uint64_t data);
+
+typedef struct {
+ uint64_t field_data;
+ _upb_field_parser *field_parser;
+} _upb_fasttable_entry;
+
typedef struct upb_msglayout {
const struct upb_msglayout *const* submsgs;
const upb_msglayout_field *fields;
@@ -54,6 +68,10 @@ typedef struct upb_msglayout {
uint16_t size;
uint16_t field_count;
bool extendable;
+ uint8_t table_mask;
+ /* To constant-initialize the tables of variable length, we need a flexible
+ * array member, and we need to compile in C99 mode. */
+ _upb_fasttable_entry fasttable[];
} upb_msglayout;
/** upb_msg *******************************************************************/
@@ -62,25 +80,42 @@ typedef struct upb_msglayout {
* compatibility. We put these before the user's data. The user's upb_msg*
* points after the upb_msg_internal. */
-/* Used when a message is not extendable. */
typedef struct {
- char *unknown;
- size_t unknown_len;
- size_t unknown_size;
-} upb_msg_internal;
+ uint32_t len;
+ uint32_t size;
+ /* Data follows. */
+} upb_msg_unknowndata;
-/* Used when a message is extendable. */
+/* Used when a message is not extendable. */
typedef struct {
- upb_inttable *extdict;
- upb_msg_internal base;
-} upb_msg_internal_withext;
+ upb_msg_unknowndata *unknown;
+} upb_msg_internal;
/* Maps upb_fieldtype_t -> memory size. */
extern char _upb_fieldtype_to_size[12];
+UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) {
+ return l->size + sizeof(upb_msg_internal);
+}
+
+UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) {
+ size_t size = upb_msg_sizeof(l);
+ void *mem = upb_arena_malloc(a, size);
+ upb_msg *msg;
+ if (UPB_UNLIKELY(!mem)) return NULL;
+ msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg);
+ memset(mem, 0, size);
+ return msg;
+}
+
/* Creates a new messages with the given layout on the given arena. */
upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
+UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
+ ptrdiff_t size = sizeof(upb_msg_internal);
+ return (upb_msg_internal*)((char*)msg - size);
+}
+
/* Clears the given message. */
void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l);
@@ -173,27 +208,49 @@ typedef struct {
uintptr_t data; /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
size_t len; /* Measured in elements. */
size_t size; /* Measured in elements. */
+ uint64_t junk;
} upb_array;
UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
+ UPB_ASSERT((arr->data & 7) <= 4);
return (void*)(arr->data & ~(uintptr_t)7);
}
+UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) {
+ UPB_ASSERT(elem_size_lg2 <= 4);
+ return (uintptr_t)ptr | elem_size_lg2;
+}
+
UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
return (void*)_upb_array_constptr(arr);
}
-/* Creates a new array on the given arena. */
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type);
+UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) {
+ UPB_ASSERT(elem_size_lg2 <= 4);
+ UPB_ASSERT(((uintptr_t)ptr & 7) == 0);
+ return (uintptr_t)ptr | (unsigned)elem_size_lg2;
+}
+
+UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size,
+ int elem_size_lg2) {
+ const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8);
+ const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2);
+ upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes);
+ if (!arr) return NULL;
+ arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2);
+ arr->len = 0;
+ arr->size = init_size;
+ return arr;
+}
/* Resizes the capacity of the array to be at least min_size. */
bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
/* Fallback functions for when the accessors require a resize. */
void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
- upb_fieldtype_t type, upb_arena *arena);
+ int elem_size_lg2, upb_arena *arena);
bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
- upb_fieldtype_t type, upb_arena *arena);
+ int elem_size_lg2, upb_arena *arena);
UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size,
upb_arena *arena) {
@@ -232,29 +289,28 @@ UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
}
}
-UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
- upb_fieldtype_t type,
- upb_arena *arena) {
- upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
+UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size,
+ int elem_size_lg2,
+ upb_arena *arena) {
+ upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *);
upb_array *arr = *arr_ptr;
if (!arr || arr->size < size) {
- return _upb_array_resize_fallback(arr_ptr, size, type, arena);
+ return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena);
}
arr->len = size;
return _upb_array_ptr(arr);
}
-
-UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
- size_t elem_size,
- upb_fieldtype_t type,
- const void *value,
- upb_arena *arena) {
- upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
+UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs,
+ int elem_size_lg2,
+ const void *value,
+ upb_arena *arena) {
+ upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *);
+ size_t elem_size = 1 << elem_size_lg2;
upb_array *arr = *arr_ptr;
- void* ptr;
+ void *ptr;
if (!arr || arr->len == arr->size) {
- return _upb_array_append_fallback(arr_ptr, value, type, arena);
+ return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena);
}
ptr = _upb_array_ptr(arr);
memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
@@ -262,6 +318,42 @@ UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
return true;
}
+/* Used by old generated code, remove once all code has been regenerated. */
+UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_BOOL:
+ return 0;
+ case UPB_TYPE_FLOAT:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_ENUM:
+ return 2;
+ case UPB_TYPE_MESSAGE:
+ return UPB_SIZE(2, 3);
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ return 3;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ return UPB_SIZE(3, 4);
+ }
+ UPB_UNREACHABLE();
+}
+UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
+ upb_fieldtype_t type,
+ upb_arena *arena) {
+ return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena);
+}
+UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
+ size_t elem_size, upb_fieldtype_t type,
+ const void *value,
+ upb_arena *arena) {
+ (void)elem_size;
+ return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+ arena);
+}
+
/** upb_map *******************************************************************/
/* Right now we use strmaps for everything. We'll likely want to use
@@ -318,17 +410,17 @@ UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
}
}
-UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size,
- upb_arena *a) {
- upb_value ret = {0};
+UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval,
+ upb_arena *a) {
if (size == UPB_MAPTYPE_STRING) {
upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
+ if (!strp) return false;
*strp = *(upb_strview*)val;
- ret = upb_value_ptr(strp);
+ *msgval = upb_value_ptr(strp);
} else {
- memcpy(&ret, val, size);
+ memcpy(msgval, val, size);
}
- return ret;
+ return true;
}
UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
@@ -370,7 +462,8 @@ UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
void *val, size_t val_size, upb_arena *arena) {
upb_strview strkey = _upb_map_tokey(key, key_size);
- upb_value tabval = _upb_map_tovalue(val, val_size, arena);
+ upb_value tabval = {0};
+ if (!_upb_map_tovalue(val, val_size, &tabval, arena)) return false;
upb_alloc *a = upb_arena_alloc(arena);
/* TODO(haberman): add overwrite operation to minimize number of lookups. */
@@ -462,6 +555,53 @@ UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size)
}
}
+/** _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 maps).
+ * _upb_mapsorter can contain a stack of maps. */
+
+typedef struct {
+ upb_tabent const**entries;
+ int size;
+ int cap;
+} _upb_mapsorter;
+
+typedef struct {
+ int start;
+ int pos;
+ int end;
+} _upb_sortedmap;
+
+UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) {
+ s->entries = NULL;
+ s->size = 0;
+ s->cap = 0;
+}
+
+UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) {
+ if (s->entries) free(s->entries);
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+ const upb_map *map, _upb_sortedmap *sorted);
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) {
+ s->size = sorted->start;
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map,
+ _upb_sortedmap *sorted,
+ upb_map_entry *ent) {
+ if (sorted->pos == sorted->end) return false;
+ const upb_tabent *tabent = s->entries[sorted->pos++];
+ upb_strview key = upb_tabstrview(tabent->key);
+ _upb_map_fromkey(key, &ent->k, map->key_size);
+ upb_value val = {tabent->val.val};
+ _upb_map_fromvalue(val, &ent->v, map->val_size);
+ return true;
+}
+
#undef PTR_AT
#ifdef __cplusplus
diff --git a/contrib/libs/grpc/third_party/upb/upb/port.c b/contrib/libs/grpc/third_party/upb/upb/port.c
deleted file mode 100644
index 9ecf135167..0000000000
--- a/contrib/libs/grpc/third_party/upb/upb/port.c
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include "upb/port_def.inc"
-
-#ifdef UPB_MSVC_VSNPRINTF
-/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and
- * vsnprintf. To support them, missing functions are manually implemented
- * using the existing secure functions. */
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) {
- if (!s) {
- return _vscprintf(format, arg);
- }
- int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg);
- if (ret < 0) {
- ret = _vscprintf(format, arg);
- }
- return ret;
-}
-
-int msvc_snprintf(char* s, size_t n, const char* format, ...) {
- va_list arg;
- va_start(arg, format);
- int ret = msvc_vsnprintf(s, n, format, arg);
- va_end(arg);
- return ret;
-}
-#endif
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 2c144dc066..2cd1bb6985 100644
--- a/contrib/libs/grpc/third_party/upb/upb/port_def.inc
+++ b/contrib/libs/grpc/third_party/upb/upb/port_def.inc
@@ -20,6 +20,13 @@
*
* This file is private and must not be included by users!
*/
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+ (defined(__cplusplus) && __cplusplus >= 201103L) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
#include <stdint.h>
#include <stddef.h>
@@ -68,66 +75,21 @@
#define UPB_UNLIKELY(x) (x)
#endif
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
/* Macros for function attributes on compilers that support them. */
#ifdef __GNUC__
#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
#define UPB_NOINLINE __attribute__((noinline))
#define UPB_NORETURN __attribute__((__noreturn__))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
#else /* !defined(__GNUC__) */
#define UPB_FORCEINLINE
#define UPB_NOINLINE
#define UPB_NORETURN
#endif
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
- (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
@@ -155,25 +117,76 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
#define UPB_ASSERT(expr) assert(expr)
#endif
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode. This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
#if defined(__GNUC__) || defined(__clang__)
#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
#else
#define UPB_UNREACHABLE() do { assert(0); } while(0)
#endif
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#if defined(__x86_64__) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64 + Clang/GCC only
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
#else
-#define UPB_INFINITY (1.0 / 0.0)
+#define UPB_FASTTABLE 0
#endif
-#ifdef NAN
-#define UPB_NAN NAN
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
#else
-#define UPB_NAN (0.0 / 0.0)
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+ __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+ __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+ ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+ ((void)(addr), (void)(size))
+#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 c2b5f4a322..b7be52cc98 100644
--- a/contrib/libs/grpc/third_party/upb/upb/port_undef.inc
+++ b/contrib/libs/grpc/third_party/upb/upb/port_undef.inc
@@ -18,11 +18,7 @@
#undef UPB_UNUSED
#undef UPB_ASSUME
#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_NAN
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/contrib/libs/grpc/third_party/upb/upb/reflection.c b/contrib/libs/grpc/third_party/upb/upb/reflection.c
new file mode 100644
index 0000000000..a233d964e9
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/reflection.c
@@ -0,0 +1,408 @@
+
+#include "upb/reflection.h"
+
+#include <string.h>
+#include "upb/table.int.h"
+#include "upb/msg.h"
+
+#include "upb/port_def.inc"
+
+static size_t get_field_size(const upb_msglayout_field *f) {
+ static unsigned char sizes[] = {
+ 0,/* 0 */
+ 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
+ 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
+ 8, /* UPB_DESCRIPTOR_TYPE_INT64 */
+ 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
+ 4, /* UPB_DESCRIPTOR_TYPE_INT32 */
+ 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
+ 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
+ 1, /* UPB_DESCRIPTOR_TYPE_BOOL */
+ sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
+ sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
+ sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
+ sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
+ 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
+ 4, /* UPB_DESCRIPTOR_TYPE_ENUM */
+ 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
+ 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
+ 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
+ 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
+ };
+ return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype];
+}
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_fieldtype_to_mapsize[12] = {
+ 0,
+ 1, /* UPB_TYPE_BOOL */
+ 4, /* UPB_TYPE_FLOAT */
+ 4, /* UPB_TYPE_INT32 */
+ 4, /* UPB_TYPE_UINT32 */
+ 4, /* UPB_TYPE_ENUM */
+ sizeof(void*), /* UPB_TYPE_MESSAGE */
+ 8, /* UPB_TYPE_DOUBLE */
+ 8, /* UPB_TYPE_INT64 */
+ 8, /* UPB_TYPE_UINT64 */
+ 0, /* UPB_TYPE_STRING */
+ 0, /* UPB_TYPE_BYTES */
+};
+
+static const char _upb_fieldtype_to_sizelg2[12] = {
+ 0,
+ 0, /* UPB_TYPE_BOOL */
+ 2, /* UPB_TYPE_FLOAT */
+ 2, /* UPB_TYPE_INT32 */
+ 2, /* UPB_TYPE_UINT32 */
+ 2, /* UPB_TYPE_ENUM */
+ UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */
+ 3, /* UPB_TYPE_DOUBLE */
+ 3, /* UPB_TYPE_INT64 */
+ 3, /* UPB_TYPE_UINT64 */
+ UPB_SIZE(3, 4), /* UPB_TYPE_STRING */
+ UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */
+};
+
+/** upb_msg *******************************************************************/
+
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
+ return _upb_msg_new(upb_msgdef_layout(m), a);
+}
+
+static bool in_oneof(const upb_msglayout_field *field) {
+ return field->presence < 0;
+}
+
+static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ const char *mem = UPB_PTR_AT(msg, field->offset, char);
+ upb_msgval val = {0};
+ memcpy(&val, mem, get_field_size(field));
+ return val;
+}
+
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ if (in_oneof(field)) {
+ return _upb_getoneofcase_field(msg, field) == field->number;
+ } else if (field->presence > 0) {
+ return _upb_hasbit_field(msg, field);
+ } else {
+ UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+ field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
+ return _upb_msg_getraw(msg, f).msg_val != NULL;
+ }
+}
+
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+ const upb_oneofdef *o) {
+ const upb_fielddef *f = upb_oneofdef_field(o, 0);
+ if (upb_oneofdef_issynthetic(o)) {
+ UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1);
+ return upb_msg_has(msg, f) ? f : NULL;
+ } else {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+ f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL;
+ UPB_ASSERT((f != NULL) == (oneof_case != 0));
+ return f;
+ }
+}
+
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
+ if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+ return _upb_msg_getraw(msg, f);
+ } else {
+ /* TODO(haberman): change upb_fielddef to not require this switch(). */
+ upb_msgval val = {0};
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_ENUM:
+ val.int32_val = upb_fielddef_defaultint32(f);
+ break;
+ case UPB_TYPE_INT64:
+ val.int64_val = upb_fielddef_defaultint64(f);
+ break;
+ case UPB_TYPE_UINT32:
+ val.uint32_val = upb_fielddef_defaultuint32(f);
+ break;
+ case UPB_TYPE_UINT64:
+ val.uint64_val = upb_fielddef_defaultuint64(f);
+ break;
+ case UPB_TYPE_FLOAT:
+ val.float_val = upb_fielddef_defaultfloat(f);
+ break;
+ case UPB_TYPE_DOUBLE:
+ val.double_val = upb_fielddef_defaultdouble(f);
+ break;
+ case UPB_TYPE_BOOL:
+ val.bool_val = upb_fielddef_defaultbool(f);
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
+ break;
+ case UPB_TYPE_MESSAGE:
+ val.msg_val = NULL;
+ break;
+ }
+ return val;
+ }
+}
+
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
+ upb_arena *a) {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ upb_mutmsgval ret;
+ char *mem = UPB_PTR_AT(msg, field->offset, char);
+ bool wrong_oneof =
+ in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number;
+
+ memcpy(&ret, mem, sizeof(void*));
+
+ if (a && (!ret.msg || wrong_oneof)) {
+ if (upb_fielddef_ismap(f)) {
+ const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
+ const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
+ ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
+ } else if (upb_fielddef_isseq(f)) {
+ ret.array = upb_array_new(a, upb_fielddef_type(f));
+ } else {
+ UPB_ASSERT(upb_fielddef_issubmsg(f));
+ ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
+ }
+
+ memcpy(mem, &ret, sizeof(void*));
+
+ if (wrong_oneof) {
+ *_upb_oneofcase_field(msg, field) = field->number;
+ } else if (field->presence > 0) {
+ _upb_sethas_field(msg, field);
+ }
+ }
+ return ret;
+}
+
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+ upb_arena *a) {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ char *mem = UPB_PTR_AT(msg, field->offset, char);
+ UPB_UNUSED(a); /* We reserve the right to make set insert into a map. */
+ memcpy(mem, &val, get_field_size(field));
+ if (field->presence > 0) {
+ _upb_sethas_field(msg, field);
+ } else if (in_oneof(field)) {
+ *_upb_oneofcase_field(msg, field) = field->number;
+ }
+}
+
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) {
+ const upb_msglayout_field *field = upb_fielddef_layout(f);
+ char *mem = UPB_PTR_AT(msg, field->offset, char);
+
+ if (field->presence > 0) {
+ _upb_clearhas_field(msg, field);
+ } else if (in_oneof(field)) {
+ uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+ if (*oneof_case != field->number) return;
+ *oneof_case = 0;
+ }
+
+ memset(mem, 0, get_field_size(field));
+}
+
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) {
+ _upb_msg_clear(msg, upb_msgdef_layout(m));
+}
+
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+ const upb_symtab *ext_pool, const upb_fielddef **out_f,
+ upb_msgval *out_val, size_t *iter) {
+ int i = *iter;
+ int n = upb_msgdef_fieldcount(m);
+ const upb_msgval zero = {0};
+ UPB_UNUSED(ext_pool);
+ while (++i < n) {
+ const upb_fielddef *f = upb_msgdef_field(m, i);
+ upb_msgval val = _upb_msg_getraw(msg, f);
+
+ /* Skip field if unset or empty. */
+ if (upb_fielddef_haspresence(f)) {
+ if (!upb_msg_has(msg, f)) continue;
+ } else {
+ upb_msgval test = val;
+ if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
+ /* Clear string pointer, only size matters (ptr could be non-NULL). */
+ test.str_val.data = NULL;
+ }
+ /* Continue if NULL or 0. */
+ if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
+
+ /* Continue on empty array or map. */
+ if (upb_fielddef_ismap(f)) {
+ if (upb_map_size(test.map_val) == 0) continue;
+ } else if (upb_fielddef_isseq(f)) {
+ if (upb_array_size(test.array_val) == 0) continue;
+ }
+ }
+
+ *out_val = val;
+ *out_f = f;
+ *iter = i;
+ return true;
+ }
+ *iter = i;
+ return false;
+}
+
+bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) {
+ size_t iter = UPB_MSG_BEGIN;
+ const upb_fielddef *f;
+ upb_msgval val;
+ bool ret = true;
+
+ if (--depth == 0) return false;
+
+ _upb_msg_discardunknown_shallow(msg);
+
+ while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+ const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+ if (!subm) continue;
+ if (upb_fielddef_ismap(f)) {
+ const upb_fielddef *val_f = upb_msgdef_itof(subm, 2);
+ const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
+ upb_map *map = (upb_map*)val.map_val;
+ size_t iter = UPB_MAP_BEGIN;
+
+ if (!val_m) continue;
+
+ while (upb_mapiter_next(map, &iter)) {
+ upb_msgval map_val = upb_mapiter_value(map, iter);
+ if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) {
+ ret = false;
+ }
+ }
+ } else if (upb_fielddef_isseq(f)) {
+ const upb_array *arr = val.array_val;
+ size_t i, n = upb_array_size(arr);
+ for (i = 0; i < n; i++) {
+ upb_msgval elem = upb_array_get(arr, i);
+ if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) {
+ ret = false;
+ }
+ }
+ } else {
+ if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) {
+ ret = false;
+ }
+ }
+ }
+
+ return ret;
+}
+
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) {
+ return _upb_msg_discardunknown(msg, m, maxdepth);
+}
+
+/** upb_array *****************************************************************/
+
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
+ return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]);
+}
+
+size_t upb_array_size(const upb_array *arr) {
+ return arr->len;
+}
+
+upb_msgval upb_array_get(const upb_array *arr, size_t i) {
+ upb_msgval 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_msgval 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_msgval val, upb_arena *arena) {
+ if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
+ return false;
+ }
+ arr->len++;
+ upb_array_set(arr, arr->len - 1, val);
+ return true;
+}
+
+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_fieldtype_t key_type,
+ upb_fieldtype_t value_type) {
+ return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
+ _upb_fieldtype_to_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_msgval key, upb_msgval *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_msgval key, upb_msgval 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_msgval key) {
+ return _upb_map_delete(map, &key, map->key_size);
+}
+
+bool upb_mapiter_next(const upb_map *map, size_t *iter) {
+ return _upb_map_next(map, iter);
+}
+
+bool upb_mapiter_done(const upb_map *map, size_t iter) {
+ upb_strtable_iter i;
+ UPB_ASSERT(iter != UPB_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_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
+ upb_strtable_iter i;
+ upb_msgval ret;
+ i.t = &map->table;
+ i.index = iter;
+ _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+ return ret;
+}
+
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
+ upb_strtable_iter i;
+ upb_msgval ret;
+ i.t = &map->table;
+ i.index = iter;
+ _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+ return ret;
+}
+
+/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
diff --git a/contrib/libs/grpc/third_party/upb/upb/reflection.h b/contrib/libs/grpc/third_party/upb/upb/reflection.h
new file mode 100644
index 0000000000..0133630c58
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/reflection.h
@@ -0,0 +1,168 @@
+
+#ifndef UPB_REFLECTION_H_
+#define UPB_REFLECTION_H_
+
+#include "upb/def.h"
+#include "upb/msg.h"
+#include "upb/upb.h"
+
+#include "upb/port_def.inc"
+
+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_msg* msg_val;
+ const upb_array* array_val;
+ upb_strview str_val;
+} upb_msgval;
+
+typedef union {
+ upb_map* map;
+ upb_msg* msg;
+ upb_array* array;
+} upb_mutmsgval;
+
+/** upb_msg *******************************************************************/
+
+/* Creates a new message of the given type in the given arena. */
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
+
+/* Returns the value associated with this field. */
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns a mutable pointer to a map, array, or submessage value. If the given
+ * arena is non-NULL this will construct a new object if it was not previously
+ * present. May not be called for primitive fields. */
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
+
+/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns the field that is set in the oneof, or NULL if none are set. */
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+ const upb_oneofdef *o);
+
+/* Sets the given field to the given value. For a msg/array/map/string, the
+ * value must be in the same arena. */
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+ upb_arena *a);
+
+/* Clears any field presence and sets the value back to its default. */
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
+
+/* Clear all data and unknown fields. */
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m);
+
+/* Iterate over present fields.
+ *
+ * size_t iter = UPB_MSG_BEGIN;
+ * const upb_fielddef *f;
+ * upb_msgval val;
+ * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
+ * process_field(f, val);
+ * }
+ *
+ * If ext_pool is NULL, no extensions will be returned. If the given symtab
+ * returns extensions that don't match what is in this message, those extensions
+ * will be skipped.
+ */
+
+#define UPB_MSG_BEGIN -1
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+ const upb_symtab *ext_pool, const upb_fielddef **f,
+ upb_msgval *val, size_t *iter);
+
+/* Adds unknown data (serialized protobuf data) to the given message. The data
+ * is copied into the message instance. */
+void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+ upb_arena *arena);
+
+/* Clears all unknown field data from this message and all submessages. */
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth);
+
+/* Returns a reference to the message's unknown data. */
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
+
+/** 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_fieldtype_t 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_msgval 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_msgval val);
+
+/* Appends an element to the array. Returns false on allocation failure. */
+bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
+
+/* 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_fieldtype_t key_type,
+ upb_fieldtype_t 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_msgval key, upb_msgval *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_msgval key, upb_msgval 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_msgval key);
+
+/* Map iteration:
+ *
+ * size_t iter = UPB_MAP_BEGIN;
+ * while (upb_mapiter_next(map, &iter)) {
+ * upb_msgval key = upb_mapiter_key(map, iter);
+ * upb_msgval val = upb_mapiter_value(map, iter);
+ *
+ * // If mutating is desired.
+ * upb_mapiter_setvalue(map, iter, value2);
+ * }
+ */
+
+/* Advances to the next entry. Returns false if no more entries are present. */
+bool upb_mapiter_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
+ * UPB_MAP_BEGIN (you must call next() at least once first). */
+bool upb_mapiter_done(const upb_map *map, size_t iter);
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
+upb_msgval upb_mapiter_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_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
+
+#include "upb/port_undef.inc"
+
+#endif /* UPB_REFLECTION_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/table.c b/contrib/libs/grpc/third_party/upb/upb/table.c
index 34a20530d8..8837047659 100644
--- a/contrib/libs/grpc/third_party/upb/upb/table.c
+++ b/contrib/libs/grpc/third_party/upb/upb/table.c
@@ -4,10 +4,12 @@
** Implementation is heavily inspired by Lua's ltable.c.
*/
-#include "upb/table.int.h"
-
#include <string.h>
+#include "third_party/wyhash/wyhash.h"
+#include "upb/table.int.h"
+
+/* Must be last. */
#include "upb/port_def.inc"
#define UPB_MAXARRSIZE 16 /* 64k. */
@@ -87,11 +89,7 @@ static upb_tabent *mutable_entries(upb_table *t) {
}
static bool isfull(upb_table *t) {
- if (upb_table_size(t) == 0) {
- return true;
- } else {
- return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
- }
+ return t->count == t->max_count;
}
static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
@@ -100,6 +98,7 @@ static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
t->count = 0;
t->size_lg2 = size_lg2;
t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+ t->max_count = upb_table_size(t) * MAX_LOAD;
bytes = upb_table_size(t) * sizeof(upb_tabent);
if (bytes > 0) {
t->entries = upb_malloc(a, bytes);
@@ -115,9 +114,17 @@ static void uninit(upb_table *t, upb_alloc *a) {
upb_free(a, mutable_entries(t));
}
-static upb_tabent *emptyent(upb_table *t) {
- upb_tabent *e = mutable_entries(t) + upb_table_size(t);
- while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
+static upb_tabent *emptyent(upb_table *t, upb_tabent *e) {
+ upb_tabent *begin = mutable_entries(t);
+ upb_tabent *end = begin + upb_table_size(t);
+ for (e = e + 1; e < end; e++) {
+ if (upb_tabent_isempty(e)) return e;
+ }
+ for (e = begin; e < end; e++) {
+ if (upb_tabent_isempty(e)) return e;
+ }
+ UPB_ASSERT(false);
+ return NULL;
}
static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
@@ -173,11 +180,11 @@ static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
our_e->next = NULL;
} else {
/* Collision. */
- upb_tabent *new_e = emptyent(t);
+ upb_tabent *new_e = emptyent(t, mainpos_e);
/* Head of collider's chain. */
upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
if (chain == mainpos_e) {
- /* Existing ent is in its main posisiton (it has the same hash as us, and
+ /* Existing ent is in its main position (it has the same hash as us, and
* is the head of our chain). Insert to new ent and append to this chain. */
new_e->next = mainpos_e->next;
mainpos_e->next = new_e;
@@ -268,10 +275,14 @@ static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
return (uintptr_t)str;
}
+static uint32_t table_hash(const char *p, size_t n) {
+ return wyhash(p, n, 0, _wyp);
+}
+
static uint32_t strhash(upb_tabkey key) {
uint32_t len;
char *str = upb_tabstr(key, &len);
- return upb_murmur_hash2(str, len, 0);
+ return table_hash(str, len);
}
static bool streql(upb_tabkey k1, lookupkey_t k2) {
@@ -280,9 +291,14 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) {
return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
}
-bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
+bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype,
+ size_t expected_size, upb_alloc *a) {
UPB_UNUSED(ctype); /* TODO(haberman): rm */
- return init(&t->t, 2, a);
+ // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator.
+ size_t need_entries = (expected_size + 1) * 1204 / 1024;
+ UPB_ASSERT(need_entries >= expected_size * 0.85);
+ int size_lg2 = _upb_lg2ceil(need_entries);
+ return init(&t->t, size_lg2, a);
}
void upb_strtable_clear(upb_strtable *t) {
@@ -333,20 +349,20 @@ bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
tabkey = strcopy(key, a);
if (tabkey == 0) return false;
- hash = upb_murmur_hash2(key.str.str, key.str.len, 0);
+ hash = table_hash(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 = upb_murmur_hash2(key, len, 0);
+ uint32_t hash = table_hash(key, len);
return lookup(&t->t, strkey2(key, len), v, hash, &streql);
}
bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
upb_value *val, upb_alloc *alloc) {
- uint32_t hash = upb_murmur_hash2(key, len, 0);
+ uint32_t hash = table_hash(key, len);
upb_tabkey tabkey;
if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
if (alloc) {
@@ -699,182 +715,3 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
return i1->t == i2->t && i1->index == i2->index &&
i1->array_part == i2->array_part;
}
-
-#if defined(UPB_UNALIGNED_READS_OK) || defined(__s390x__)
-/* -----------------------------------------------------------------------------
- * MurmurHash2, by Austin Appleby (released as public domain).
- * Reformatted and C99-ified by Joshua Haberman.
- * Note - This code makes a few assumptions about how your machine behaves -
- * 1. We can read a 4-byte value from any address without crashing
- * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
- * And it has a few limitations -
- * 1. It will not work incrementally.
- * 2. It will not produce the same results on little-endian and big-endian
- * machines. */
-uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) {
- /* 'm' and 'r' are mixing constants generated offline.
- * They're not really 'magic', they just happen to work well. */
- const uint32_t m = 0x5bd1e995;
- const int32_t r = 24;
-
- /* Initialize the hash to a 'random' value */
- uint32_t h = seed ^ len;
-
- /* Mix 4 bytes at a time into the hash */
- const uint8_t * data = (const uint8_t *)key;
- while(len >= 4) {
- uint32_t k;
- memcpy(&k, data, sizeof(k));
-
- k *= m;
- k ^= k >> r;
- k *= m;
-
- h *= m;
- h ^= k;
-
- data += 4;
- len -= 4;
- }
-
- /* Handle the last few bytes of the input array */
- switch(len) {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0]; h *= m;
- };
-
- /* Do a few final mixes of the hash to ensure the last few
- * bytes are well-incorporated. */
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
-}
-
-#else /* !UPB_UNALIGNED_READS_OK */
-
-/* -----------------------------------------------------------------------------
- * MurmurHashAligned2, by Austin Appleby
- * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
- * on certain platforms.
- * Performance will be lower than MurmurHash2 */
-
-#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
-
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) {
- const uint32_t m = 0x5bd1e995;
- const int32_t r = 24;
- const uint8_t * data = (const uint8_t *)key;
- uint32_t h = (uint32_t)(seed ^ len);
- uint8_t align = (uintptr_t)data & 3;
-
- if(align && (len >= 4)) {
- /* Pre-load the temp registers */
- uint32_t t = 0, d = 0;
- int32_t sl;
- int32_t sr;
-
- switch(align) {
- case 1: t |= data[2] << 16; /* fallthrough */
- case 2: t |= data[1] << 8; /* fallthrough */
- case 3: t |= data[0];
- }
-
- t <<= (8 * align);
-
- data += 4-align;
- len -= 4-align;
-
- sl = 8 * (4-align);
- sr = 8 * align;
-
- /* Mix */
-
- while(len >= 4) {
- uint32_t k;
-
- d = *(uint32_t *)data;
- t = (t >> sr) | (d << sl);
-
- k = t;
-
- MIX(h,k,m);
-
- t = d;
-
- data += 4;
- len -= 4;
- }
-
- /* Handle leftover data in temp registers */
-
- d = 0;
-
- if(len >= align) {
- uint32_t k;
-
- switch(align) {
- case 3: d |= data[2] << 16; /* fallthrough */
- case 2: d |= data[1] << 8; /* fallthrough */
- case 1: d |= data[0]; /* fallthrough */
- }
-
- k = (t >> sr) | (d << sl);
- MIX(h,k,m);
-
- data += align;
- len -= align;
-
- /* ----------
- * Handle tail bytes */
-
- switch(len) {
- case 3: h ^= data[2] << 16; /* fallthrough */
- case 2: h ^= data[1] << 8; /* fallthrough */
- case 1: h ^= data[0]; h *= m; /* fallthrough */
- };
- } else {
- switch(len) {
- case 3: d |= data[2] << 16; /* fallthrough */
- case 2: d |= data[1] << 8; /* fallthrough */
- case 1: d |= data[0]; /* fallthrough */
- case 0: h ^= (t >> sr) | (d << sl); h *= m;
- }
- }
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
- } else {
- while(len >= 4) {
- uint32_t k = *(uint32_t *)data;
-
- MIX(h,k,m);
-
- data += 4;
- len -= 4;
- }
-
- /* ----------
- * Handle tail bytes */
-
- switch(len) {
- case 3: h ^= data[2] << 16; /* fallthrough */
- case 2: h ^= data[1] << 8; /* fallthrough */
- case 1: h ^= data[0]; h *= m;
- };
-
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
-
- return h;
- }
-}
-#undef MIX
-
-#endif /* UPB_UNALIGNED_READS_OK */
diff --git a/contrib/libs/grpc/third_party/upb/upb/table.int.h b/contrib/libs/grpc/third_party/upb/upb/table.int.h
index 600637eef2..49caac463e 100644
--- a/contrib/libs/grpc/third_party/upb/upb/table.int.h
+++ b/contrib/libs/grpc/third_party/upb/upb/table.int.h
@@ -13,7 +13,7 @@
** store pointers or integers of at least 32 bits (upb isn't really useful on
** systems where sizeof(void*) < 4).
**
-** The table must be homogenous (all values of the same type). In debug
+** The table must be homogeneous (all values of the same type). In debug
** mode, we check this on insert and lookup.
*/
@@ -147,10 +147,17 @@ UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
return mem + sizeof(*len);
}
+UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) {
+ upb_strview ret;
+ uint32_t len;
+ ret.data = upb_tabstr(key, &len);
+ ret.size = len;
+ return ret;
+}
/* upb_tabval *****************************************************************/
-typedef struct {
+typedef struct upb_tabval {
uint64_t val;
} upb_tabval;
@@ -171,7 +178,8 @@ typedef struct _upb_tabent {
typedef struct {
size_t count; /* Number of entries in the hash part. */
- size_t mask; /* Mask to turn hash value -> bucket. */
+ uint32_t mask; /* Mask to turn hash value -> bucket. */
+ uint32_t max_count; /* Max count before we hit our load limit. */
uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */
/* Hash table entries.
@@ -230,7 +238,8 @@ UPB_INLINE bool upb_arrhas(upb_tabval key) {
/* Initialize and uninitialize a table, respectively. If memory allocation
* failed, false is returned that the table is uninitialized. */
bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
-bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
+bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype,
+ size_t expected_size, upb_alloc *a);
void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
@@ -239,7 +248,7 @@ UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
}
UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
- return upb_strtable_init2(table, ctype, &upb_alloc_global);
+ return upb_strtable_init2(table, ctype, 4, &upb_alloc_global);
}
UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
diff --git a/contrib/libs/grpc/third_party/upb/upb/text_encode.c b/contrib/libs/grpc/third_party/upb/upb/text_encode.c
new file mode 100644
index 0000000000..028cc29e09
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/text_encode.c
@@ -0,0 +1,421 @@
+
+#include "upb/text_encode.h"
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "upb/reflection.h"
+#include "upb/port_def.inc"
+
+typedef struct {
+ char *buf, *ptr, *end;
+ size_t overflow;
+ int indent_depth;
+ int options;
+ const upb_symtab *ext_pool;
+ _upb_mapsorter sorter;
+} txtenc;
+
+static void txtenc_msg(txtenc *e, const upb_msg *msg, const upb_msgdef *m);
+
+static void txtenc_putbytes(txtenc *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 txtenc_putstr(txtenc *e, const char *str) {
+ txtenc_putbytes(e, str, strlen(str));
+}
+
+static void txtenc_printf(txtenc *e, const char *fmt, ...) {
+ size_t n;
+ size_t have = e->end - e->ptr;
+ va_list args;
+
+ va_start(args, fmt);
+ n = vsnprintf(e->ptr, have, fmt, args);
+ va_end(args);
+
+ if (UPB_LIKELY(have > n)) {
+ e->ptr += n;
+ } else {
+ e->ptr += have;
+ e->overflow += (n - have);
+ }
+}
+
+static void txtenc_indent(txtenc *e) {
+ if ((e->options & UPB_TXTENC_SINGLELINE) == 0) {
+ int i = e->indent_depth;
+ while (i-- > 0) {
+ txtenc_putstr(e, " ");
+ }
+ }
+}
+
+static void txtenc_endfield(txtenc *e) {
+ if (e->options & UPB_TXTENC_SINGLELINE) {
+ txtenc_putstr(e, " ");
+ } else {
+ txtenc_putstr(e, "\n");
+ }
+}
+
+static void txtenc_enum(int32_t val, const upb_fielddef *f, txtenc *e) {
+ const upb_enumdef *e_def = upb_fielddef_enumsubdef(f);
+ const char *name = upb_enumdef_iton(e_def, val);
+
+ if (name) {
+ txtenc_printf(e, "%s", name);
+ } else {
+ txtenc_printf(e, "%" PRId32, val);
+ }
+}
+
+static void txtenc_string(txtenc *e, upb_strview str, bool bytes) {
+ const char *ptr = str.data;
+ const char *end = ptr + str.size;
+ txtenc_putstr(e, "\"");
+
+ while (ptr < end) {
+ switch (*ptr) {
+ case '\n':
+ txtenc_putstr(e, "\\n");
+ break;
+ case '\r':
+ txtenc_putstr(e, "\\r");
+ break;
+ case '\t':
+ txtenc_putstr(e, "\\t");
+ break;
+ case '\"':
+ txtenc_putstr(e, "\\\"");
+ break;
+ case '\'':
+ txtenc_putstr(e, "\\'");
+ break;
+ case '\\':
+ txtenc_putstr(e, "\\\\");
+ break;
+ default:
+ if ((bytes || (uint8_t)*ptr < 0x80) && !isprint(*ptr)) {
+ txtenc_printf(e, "\\%03o", (int)(uint8_t)*ptr);
+ } else {
+ txtenc_putbytes(e, ptr, 1);
+ }
+ break;
+ }
+ ptr++;
+ }
+
+ txtenc_putstr(e, "\"");
+}
+
+static void txtenc_field(txtenc *e, upb_msgval val, const upb_fielddef *f) {
+ txtenc_indent(e);
+ txtenc_printf(e, "%s: ", upb_fielddef_name(f));
+
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_BOOL:
+ txtenc_putstr(e, val.bool_val ? "true" : "false");
+ break;
+ case UPB_TYPE_FLOAT:
+ txtenc_printf(e, "%f", val.float_val);
+ break;
+ case UPB_TYPE_DOUBLE:
+ txtenc_printf(e, "%f", val.double_val);
+ break;
+ case UPB_TYPE_INT32:
+ txtenc_printf(e, "%" PRId32, val.int32_val);
+ break;
+ case UPB_TYPE_UINT32:
+ txtenc_printf(e, "%" PRIu32, val.uint32_val);
+ break;
+ case UPB_TYPE_INT64:
+ txtenc_printf(e, "%" PRId64, val.int64_val);
+ break;
+ case UPB_TYPE_UINT64:
+ txtenc_printf(e, "%" PRIu64, val.uint64_val);
+ break;
+ case UPB_TYPE_STRING:
+ txtenc_string(e, val.str_val, false);
+ break;
+ case UPB_TYPE_BYTES:
+ txtenc_string(e, val.str_val, true);
+ break;
+ case UPB_TYPE_ENUM:
+ txtenc_enum(val.int32_val, f, e);
+ break;
+ case UPB_TYPE_MESSAGE:
+ txtenc_putstr(e, "{");
+ txtenc_endfield(e);
+ e->indent_depth++;
+ txtenc_msg(e, val.msg_val, upb_fielddef_msgsubdef(f));
+ e->indent_depth--;
+ txtenc_indent(e);
+ txtenc_putstr(e, "}");
+ break;
+ }
+
+ txtenc_endfield(e);
+}
+
+/*
+ * Arrays print as simple repeated elements, eg.
+ *
+ * foo_field: 1
+ * foo_field: 2
+ * foo_field: 3
+ */
+static void txtenc_array(txtenc *e, const upb_array *arr,
+ const upb_fielddef *f) {
+ size_t i;
+ size_t size = upb_array_size(arr);
+
+ for (i = 0; i < size; i++) {
+ txtenc_field(e, upb_array_get(arr, i), f);
+ }
+}
+
+static void txtenc_mapentry(txtenc *e, upb_msgval key, upb_msgval val,
+ const upb_fielddef *f) {
+ const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *key_f = upb_msgdef_field(entry, 0);
+ const upb_fielddef *val_f = upb_msgdef_field(entry, 1);
+ txtenc_indent(e);
+ txtenc_printf(e, "%s: {", upb_fielddef_name(f));
+ txtenc_endfield(e);
+ e->indent_depth++;
+
+ txtenc_field(e, key, key_f);
+ txtenc_field(e, val, val_f);
+
+ e->indent_depth--;
+ txtenc_indent(e);
+ txtenc_putstr(e, "}");
+ txtenc_endfield(e);
+}
+
+/*
+ * Maps print as messages of key/value, etc.
+ *
+ * foo_map: {
+ * key: "abc"
+ * value: 123
+ * }
+ * foo_map: {
+ * key: "def"
+ * value: 456
+ * }
+ */
+static void txtenc_map(txtenc *e, const upb_map *map, const upb_fielddef *f) {
+ if (e->options & UPB_TXTENC_NOSORT) {
+ size_t iter = UPB_MAP_BEGIN;
+ while (upb_mapiter_next(map, &iter)) {
+ upb_msgval key = upb_mapiter_key(map, iter);
+ upb_msgval val = upb_mapiter_value(map, iter);
+ txtenc_mapentry(e, key, val, f);
+ }
+ } else {
+ const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+ const upb_fielddef *key_f = upb_msgdef_field(entry, 0);
+ _upb_sortedmap sorted;
+ upb_map_entry ent;
+
+ _upb_mapsorter_pushmap(&e->sorter, upb_fielddef_descriptortype(key_f), map,
+ &sorted);
+ while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+ upb_msgval key, val;
+ memcpy(&key, &ent.k, sizeof(key));
+ memcpy(&val, &ent.v, sizeof(val));
+ txtenc_mapentry(e, key, val, f);
+ }
+ _upb_mapsorter_popmap(&e->sorter, &sorted);
+ }
+}
+
+#define CHK(x) do { if (!(x)) { return false; } } while(0)
+
+static const char *txtenc_parsevarint(const char *ptr, const char *limit,
+ uint64_t *val) {
+ uint8_t byte;
+ int bitpos = 0;
+ *val = 0;
+
+ do {
+ CHK(bitpos < 70 && ptr < limit);
+ byte = *ptr;
+ *val |= (uint64_t)(byte & 0x7F) << bitpos;
+ ptr++;
+ bitpos += 7;
+ } while (byte & 0x80);
+
+ return ptr;
+}
+
+/*
+ * Unknown fields are printed by number.
+ *
+ * 1001: 123
+ * 1002: "hello"
+ * 1006: 0xdeadbeef
+ * 1003: {
+ * 1: 111
+ * }
+ */
+static const char *txtenc_unknown(txtenc *e, const char *ptr, const char *end,
+ int groupnum) {
+ while (ptr < end) {
+ uint64_t tag_64;
+ uint32_t tag;
+ CHK(ptr = txtenc_parsevarint(ptr, end, &tag_64));
+ CHK(tag_64 < UINT32_MAX);
+ tag = (uint32_t)tag_64;
+
+ if ((tag & 7) == UPB_WIRE_TYPE_END_GROUP) {
+ CHK((tag >> 3) == (uint32_t)groupnum);
+ return ptr;
+ }
+
+ txtenc_indent(e);
+ txtenc_printf(e, "%d: ", (int)(tag >> 3));
+
+ switch (tag & 7) {
+ case UPB_WIRE_TYPE_VARINT: {
+ uint64_t val;
+ CHK(ptr = txtenc_parsevarint(ptr, end, &val));
+ txtenc_printf(e, "%" PRIu64, val);
+ break;
+ }
+ case UPB_WIRE_TYPE_32BIT: {
+ uint32_t val;
+ CHK(end - ptr >= 4);
+ memcpy(&val, ptr, 4);
+ ptr += 4;
+ txtenc_printf(e, "0x%08" PRIu32, val);
+ break;
+ }
+ case UPB_WIRE_TYPE_64BIT: {
+ uint64_t val;
+ CHK(end - ptr >= 8);
+ memcpy(&val, ptr, 8);
+ ptr += 8;
+ txtenc_printf(e, "0x%016" PRIu64, val);
+ break;
+ }
+ case UPB_WIRE_TYPE_DELIMITED: {
+ uint64_t len;
+ size_t avail = end - ptr;
+ char *start = e->ptr;
+ size_t start_overflow = e->overflow;
+ CHK(ptr = txtenc_parsevarint(ptr, end, &len));
+ CHK(avail >= len);
+
+ /* Speculatively try to parse as message. */
+ txtenc_putstr(e, "{");
+ txtenc_endfield(e);
+ e->indent_depth++;
+ if (txtenc_unknown(e, ptr, end, -1)) {
+ e->indent_depth--;
+ txtenc_indent(e);
+ txtenc_putstr(e, "}");
+ } else {
+ /* Didn't work out, print as raw bytes. */
+ upb_strview str;
+ e->indent_depth--;
+ e->ptr = start;
+ e->overflow = start_overflow;
+ str.data = ptr;
+ str.size = len;
+ txtenc_string(e, str, true);
+ }
+ ptr += len;
+ break;
+ }
+ case UPB_WIRE_TYPE_START_GROUP:
+ txtenc_putstr(e, "{");
+ txtenc_endfield(e);
+ e->indent_depth++;
+ CHK(ptr = txtenc_unknown(e, ptr, end, tag >> 3));
+ e->indent_depth--;
+ txtenc_indent(e);
+ txtenc_putstr(e, "}");
+ break;
+ }
+ txtenc_endfield(e);
+ }
+
+ return groupnum == -1 ? ptr : NULL;
+}
+
+#undef CHK
+
+static void txtenc_msg(txtenc *e, const upb_msg *msg,
+ const upb_msgdef *m) {
+ size_t iter = UPB_MSG_BEGIN;
+ const upb_fielddef *f;
+ upb_msgval val;
+
+ while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) {
+ if (upb_fielddef_ismap(f)) {
+ txtenc_map(e, val.map_val, f);
+ } else if (upb_fielddef_isseq(f)) {
+ txtenc_array(e, val.array_val, f);
+ } else {
+ txtenc_field(e, val, f);
+ }
+ }
+
+ if ((e->options & UPB_TXTENC_SKIPUNKNOWN) == 0) {
+ size_t len;
+ const char *ptr = upb_msg_getunknown(msg, &len);
+ char *start = e->ptr;
+ if (ptr) {
+ if (!txtenc_unknown(e, ptr, ptr + len, -1)) {
+ /* Unknown failed to parse, back up and don't print it at all. */
+ e->ptr = start;
+ }
+ }
+ }
+}
+
+size_t txtenc_nullz(txtenc *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_text_encode(const upb_msg *msg, const upb_msgdef *m,
+ const upb_symtab *ext_pool, int options, char *buf,
+ size_t size) {
+ txtenc e;
+
+ e.buf = buf;
+ e.ptr = buf;
+ e.end = buf + size;
+ e.overflow = 0;
+ e.indent_depth = 0;
+ e.options = options;
+ e.ext_pool = ext_pool;
+ _upb_mapsorter_init(&e.sorter);
+
+ txtenc_msg(&e, msg, m);
+ _upb_mapsorter_destroy(&e.sorter);
+ return txtenc_nullz(&e, size);
+}
diff --git a/contrib/libs/grpc/third_party/upb/upb/text_encode.h b/contrib/libs/grpc/third_party/upb/upb/text_encode.h
new file mode 100644
index 0000000000..4ad3d1c4d7
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/text_encode.h
@@ -0,0 +1,38 @@
+
+#ifndef UPB_TEXTENCODE_H_
+#define UPB_TEXTENCODE_H_
+
+#include "upb/def.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ /* When set, prints everything on a single line. */
+ UPB_TXTENC_SINGLELINE = 1,
+
+ /* When set, unknown fields are not printed. */
+ UPB_TXTENC_SKIPUNKNOWN = 2,
+
+ /* When set, maps are *not* sorted (this avoids allocating tmp mem). */
+ UPB_TXTENC_NOSORT = 4
+};
+
+/* Encodes the given |msg| to text 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_text_encode(const upb_msg *msg, const upb_msgdef *m,
+ const upb_symtab *ext_pool, int options, char *buf,
+ size_t size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* UPB_TEXTENCODE_H_ */
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.c b/contrib/libs/grpc/third_party/upb/upb/upb.c
index 3089c059e1..a12656973d 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb.c
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.c
@@ -1,5 +1,5 @@
-#include "upb/upb.h"
+#include "upb/upb.int.h"
#include <errno.h>
#include <stdarg.h>
@@ -40,7 +40,7 @@ void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
if (!status) return;
status->ok = false;
- _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+ vsnprintf(status->msg, sizeof(status->msg), fmt, args);
status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
}
@@ -49,7 +49,7 @@ void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) {
if (!status) return;
status->ok = false;
len = strlen(status->msg);
- _upb_vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+ vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
}
@@ -73,37 +73,18 @@ upb_alloc upb_alloc_global = {&upb_global_allocfunc};
/* Be conservative and choose 16 in case anyone is using SSE. */
-typedef struct mem_block {
+struct mem_block {
struct mem_block *next;
uint32_t size;
uint32_t cleanups;
/* Data follows. */
-} mem_block;
+};
typedef struct cleanup_ent {
upb_cleanup_func *cleanup;
void *ud;
} cleanup_ent;
-struct upb_arena {
- _upb_arena_head head;
- uint32_t *cleanups;
-
- /* Allocator to allocate arena blocks. We are responsible for freeing these
- * when we are destroyed. */
- upb_alloc *block_alloc;
- uint32_t last_size;
-
- /* When multiple arenas are fused together, each arena points to a parent
- * arena (root points to itself). The root tracks how many live arenas
- * reference it. */
- uint32_t refcount; /* Only used when a->parent == a */
- struct upb_arena *parent;
-
- /* Linked list of blocks to free/cleanup. */
- mem_block *freelist, *freelist_tail;
-};
-
static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
static upb_arena *arena_findroot(upb_arena *a) {
@@ -117,9 +98,9 @@ static upb_arena *arena_findroot(upb_arena *a) {
return a;
}
-static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) {
+static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr,
+ size_t size) {
mem_block *block = ptr;
- upb_arena *root = arena_findroot(a);
/* The block is for arena |a|, but should appear in the freelist of |root|. */
block->next = root->freelist;
@@ -133,26 +114,22 @@ static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) {
a->head.end = UPB_PTR_AT(block, size, char);
a->cleanups = &block->cleanups;
- /* TODO(haberman): ASAN poison. */
+ 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(a->block_alloc, block_size);
+ mem_block *block = upb_malloc(root->block_alloc, block_size);
if (!block) return false;
- upb_arena_addblock(a, block, block_size);
+ upb_arena_addblock(a, root, block, block_size);
return true;
}
-static bool arena_has(upb_arena *a, size_t size) {
- _upb_arena_head *h = (_upb_arena_head*)a;
- return (size_t)(h->end - h->ptr) >= size;
-}
-
void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */
- UPB_ASSERT(arena_has(a, size));
+ UPB_ASSERT(_upb_arenahas(a) >= size);
return upb_arena_malloc(a, size);
}
@@ -184,7 +161,7 @@ upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
a->freelist = NULL;
a->freelist_tail = NULL;
- upb_arena_addblock(a, mem, n);
+ upb_arena_addblock(a, a, mem, n);
return a;
}
@@ -201,15 +178,14 @@ upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
}
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->last_size = 128;
+ a->last_size = UPB_MAX(128, n);
a->head.ptr = mem;
- a->head.end = UPB_PTR_AT(mem, n, char);
+ a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
a->freelist = NULL;
a->cleanups = NULL;
@@ -247,14 +223,15 @@ void upb_arena_free(upb_arena *a) {
bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
cleanup_ent *ent;
- if (!a->cleanups || !arena_has(a, sizeof(cleanup_ent))) {
+ if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */
- UPB_ASSERT(arena_has(a, sizeof(cleanup_ent)));
+ UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent));
}
a->head.end -= sizeof(cleanup_ent);
ent = (cleanup_ent*)a->head.end;
(*a->cleanups)++;
+ UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
ent->cleanup = func;
ent->ud = ud;
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.h b/contrib/libs/grpc/third_party/upb/upb/upb.h
index e1d9d8cfd3..11c0e4dc99 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb.h
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.h
@@ -161,17 +161,35 @@ 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_arena_head *h = (_upb_arena_head*)a;
+ return (size_t)(h->end - h->ptr);
+}
+
UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
_upb_arena_head *h = (_upb_arena_head*)a;
void* ret;
size = UPB_ALIGN_MALLOC(size);
- if (UPB_UNLIKELY((size_t)(h->end - h->ptr) < 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;
}
@@ -283,7 +301,7 @@ UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) {
return val;
} else {
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
- ((val & 0xff0000ULL) >> 8) | ((val & 0xff000000ULL) >> 24);
+ ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
@@ -291,14 +309,25 @@ UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) {
if (_upb_isle()) {
return val;
} else {
- return ((val & 0xff) << 56) | ((val & 0xff00) << 40) |
- ((val & 0xff0000) << 24) | ((val & 0xff000000) << 8) |
- ((val & 0xff00000000ULL) >> 8) | ((val & 0xff0000000000ULL) >> 24) |
- ((val & 0xff000000000000ULL) >> 40) |
- ((val & 0xff00000000000000ULL) >> 56);
+ return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32);
}
}
+UPB_INLINE int _upb_lg2ceil(int x) {
+ if (x <= 1) return 0;
+#ifdef __GNUC__
+ return 32 - __builtin_clz(x - 1);
+#else
+ int lg2 = 0;
+ while (1 << lg2 < x) lg2++;
+ return lg2;
+#endif
+}
+
+UPB_INLINE int _upb_lg2ceilsize(int x) {
+ return 1 << _upb_lg2ceil(x);
+}
+
#include "upb/port_undef.inc"
#ifdef __cplusplus
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.hpp b/contrib/libs/grpc/third_party/upb/upb/upb.hpp
index a3ec5faff8..b7b99761fb 100644
--- a/contrib/libs/grpc/third_party/upb/upb/upb.hpp
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.hpp
@@ -41,6 +41,9 @@ class Arena {
public:
// A simple arena with no initial memory block and the default allocator.
Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
+ Arena(char *initial_block, size_t size)
+ : ptr_(upb_arena_init(initial_block, size, &upb_alloc_global),
+ upb_arena_free) {}
upb_arena* ptr() { return ptr_.get(); }
@@ -71,15 +74,12 @@ class Arena {
template <int N>
class InlinedArena : public Arena {
public:
- InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
-
- upb_arena* ptr() { return ptr_.get(); }
+ InlinedArena() : Arena(initial_block_, N) {}
private:
InlinedArena(const InlinedArena*) = delete;
InlinedArena& operator=(const InlinedArena*) = delete;
- std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
char initial_block_[N];
};
diff --git a/contrib/libs/grpc/third_party/upb/upb/upb.int.h b/contrib/libs/grpc/third_party/upb/upb/upb.int.h
new file mode 100644
index 0000000000..b857560e4e
--- /dev/null
+++ b/contrib/libs/grpc/third_party/upb/upb/upb.int.h
@@ -0,0 +1,29 @@
+
+#ifndef UPB_INT_H_
+#define UPB_INT_H_
+
+#include "upb/upb.h"
+
+struct mem_block;
+typedef struct mem_block mem_block;
+
+struct upb_arena {
+ _upb_arena_head head;
+ uint32_t *cleanups;
+
+ /* Allocator to allocate arena blocks. We are responsible for freeing these
+ * when we are destroyed. */
+ upb_alloc *block_alloc;
+ uint32_t last_size;
+
+ /* When multiple arenas are fused together, each arena points to a parent
+ * arena (root points to itself). The root tracks how many live arenas
+ * reference it. */
+ uint32_t refcount; /* Only used when a->parent == a */
+ struct upb_arena *parent;
+
+ /* Linked list of blocks to free/cleanup. */
+ mem_block *freelist, *freelist_tail;
+};
+
+#endif /* UPB_INT_H_ */