ruby_memprofiler_pprof 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +7 -0
  2. data/ext/ruby_memprofiler_pprof/backtrace.c +429 -0
  3. data/ext/ruby_memprofiler_pprof/collector.c +1055 -0
  4. data/ext/ruby_memprofiler_pprof/compat.c +182 -0
  5. data/ext/ruby_memprofiler_pprof/extconf.rb +72 -0
  6. data/ext/ruby_memprofiler_pprof/pprof.upb.c +170 -0
  7. data/ext/ruby_memprofiler_pprof/pprof.upb.h +848 -0
  8. data/ext/ruby_memprofiler_pprof/pprof_out.c +285 -0
  9. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.c +11 -0
  10. data/ext/ruby_memprofiler_pprof/ruby_memprofiler_pprof.h +301 -0
  11. data/ext/ruby_memprofiler_pprof/strtab.c +391 -0
  12. data/ext/ruby_memprofiler_pprof/vendor/upb/BUILD +719 -0
  13. data/ext/ruby_memprofiler_pprof/vendor/upb/CONTRIBUTING.md +37 -0
  14. data/ext/ruby_memprofiler_pprof/vendor/upb/DESIGN.md +201 -0
  15. data/ext/ruby_memprofiler_pprof/vendor/upb/LICENSE +26 -0
  16. data/ext/ruby_memprofiler_pprof/vendor/upb/README.md +78 -0
  17. data/ext/ruby_memprofiler_pprof/vendor/upb/WORKSPACE +58 -0
  18. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/BUILD +53 -0
  19. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/amalgamate.py +129 -0
  20. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/build_defs.bzl +160 -0
  21. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/lua.BUILD +127 -0
  22. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/protobuf.patch +54 -0
  23. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/py_proto_library.bzl +137 -0
  24. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/python_downloads.bzl +84 -0
  25. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/system_python.bzl +101 -0
  26. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/upb_proto_library.bzl +388 -0
  27. data/ext/ruby_memprofiler_pprof/vendor/upb/bazel/workspace_deps.bzl +89 -0
  28. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD +252 -0
  29. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/BUILD.googleapis +54 -0
  30. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/benchmark.cc +333 -0
  31. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/build_defs.bzl +88 -0
  32. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/compare.py +118 -0
  33. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor.proto +888 -0
  34. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/descriptor_sv.proto +890 -0
  35. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/empty.proto +6 -0
  36. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_protobuf_binary_cc.py +64 -0
  37. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_synthetic_protos.py +118 -0
  38. data/ext/ruby_memprofiler_pprof/vendor/upb/benchmarks/gen_upb_binary_c.py +65 -0
  39. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/BUILD.bazel +102 -0
  40. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/README.md +23 -0
  41. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/build_defs.bzl +73 -0
  42. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/make_cmakelists.py +340 -0
  43. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test.py +57 -0
  44. data/ext/ruby_memprofiler_pprof/vendor/upb/cmake/staleness_test_lib.py +186 -0
  45. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/render.py +43 -0
  46. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/style-guide.md +65 -0
  47. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/vs-cpp-protos.md +255 -0
  48. data/ext/ruby_memprofiler_pprof/vendor/upb/docs/wrapping-upb.md +444 -0
  49. data/ext/ruby_memprofiler_pprof/vendor/upb/python/BUILD +216 -0
  50. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.c +394 -0
  51. data/ext/ruby_memprofiler_pprof/vendor/upb/python/convert.h +63 -0
  52. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.c +1694 -0
  53. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor.h +80 -0
  54. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.c +704 -0
  55. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_containers.h +114 -0
  56. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.c +650 -0
  57. data/ext/ruby_memprofiler_pprof/vendor/upb/python/descriptor_pool.h +48 -0
  58. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/BUILD.bazel +193 -0
  59. data/ext/ruby_memprofiler_pprof/vendor/upb/python/dist/dist.bzl +190 -0
  60. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.c +247 -0
  61. data/ext/ruby_memprofiler_pprof/vendor/upb/python/extension_dict.h +39 -0
  62. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.c +522 -0
  63. data/ext/ruby_memprofiler_pprof/vendor/upb/python/map.h +66 -0
  64. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.c +1909 -0
  65. data/ext/ruby_memprofiler_pprof/vendor/upb/python/message.h +101 -0
  66. data/ext/ruby_memprofiler_pprof/vendor/upb/python/minimal_test.py +183 -0
  67. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/BUILD +70 -0
  68. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/README.md +11 -0
  69. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_database_test_wrapper.py +30 -0
  70. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_pool_test_wrapper.py +45 -0
  71. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/descriptor_test_wrapper.py +46 -0
  72. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/generator_test_wrapper.py +30 -0
  73. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/json_format_test_wrapper.py +30 -0
  74. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/keywords_test_wrapper.py +30 -0
  75. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_factory_test_wrapper.py +37 -0
  76. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/message_test_wrapper.py +52 -0
  77. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/proto_builder_test_wrapper.py +32 -0
  78. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/pyproto_test_wrapper.bzl +36 -0
  79. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/reflection_test_wrapper.py +45 -0
  80. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/service_reflection_test_wrapper.py +30 -0
  81. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/symbol_database_test_wrapper.py +30 -0
  82. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_encoding_test_wrapper.py +30 -0
  83. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/text_format_test_wrapper.py +30 -0
  84. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/unknown_fields_test_wrapper.py +30 -0
  85. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/well_known_types_test_wrapper.py +36 -0
  86. data/ext/ruby_memprofiler_pprof/vendor/upb/python/pb_unit_tests/wire_format_test_wrapper.py +30 -0
  87. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.c +350 -0
  88. data/ext/ruby_memprofiler_pprof/vendor/upb/python/protobuf.h +230 -0
  89. data/ext/ruby_memprofiler_pprof/vendor/upb/python/py_extension.bzl +55 -0
  90. data/ext/ruby_memprofiler_pprof/vendor/upb/python/python_api.h +61 -0
  91. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.c +828 -0
  92. data/ext/ruby_memprofiler_pprof/vendor/upb/python/repeated.h +69 -0
  93. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.c +404 -0
  94. data/ext/ruby_memprofiler_pprof/vendor/upb/python/unknown_fields.h +39 -0
  95. data/ext/ruby_memprofiler_pprof/vendor/upb/python/version_script.lds +6 -0
  96. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/LICENSE +32 -0
  97. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/README.google +9 -0
  98. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/console.lua +156 -0
  99. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/lunit/lunit.lua +725 -0
  100. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/BUILD +19 -0
  101. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/LICENSE +21 -0
  102. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/naive.c +92 -0
  103. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-neon.c +157 -0
  104. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/range2-sse.c +170 -0
  105. data/ext/ruby_memprofiler_pprof/vendor/upb/third_party/utf8_range/utf8_range.h +9 -0
  106. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/BUILD.bazel +129 -0
  107. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/README.md +8 -0
  108. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/def.c +939 -0
  109. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/lua_proto_library.bzl +138 -0
  110. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/main.c +83 -0
  111. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/msg.c +1118 -0
  112. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test.proto +69 -0
  113. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/test_upb.lua +846 -0
  114. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.c +258 -0
  115. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.h +132 -0
  116. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upb.lua +58 -0
  117. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/bindings/lua/upbc.cc +134 -0
  118. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.c +192 -0
  119. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/collections.h +174 -0
  120. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb.c +346 -0
  121. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/conformance_upb_failures.txt +1 -0
  122. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.c +1221 -0
  123. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode.h +94 -0
  124. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.c +1055 -0
  125. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_fast.h +153 -0
  126. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/decode_internal.h +211 -0
  127. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.c +3262 -0
  128. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.h +414 -0
  129. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/def.hpp +438 -0
  130. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/empty.proto +1 -0
  131. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.c +604 -0
  132. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/encode.h +71 -0
  133. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/BUILD +13 -0
  134. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/fuzz/file_descriptor_parsenew_fuzzer.cc +43 -0
  135. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.c +1509 -0
  136. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_decode.h +47 -0
  137. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.c +776 -0
  138. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/json_encode.h +62 -0
  139. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.c +1147 -0
  140. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.h +189 -0
  141. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table.hpp +112 -0
  142. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.c +363 -0
  143. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors.h +263 -0
  144. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_internal.h +59 -0
  145. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_accessors_test.cc +425 -0
  146. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/mini_table_test.cc +230 -0
  147. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.c +428 -0
  148. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg.h +114 -0
  149. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_internal.h +836 -0
  150. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.cc +491 -0
  151. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/msg_test.proto +195 -0
  152. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_def.inc +261 -0
  153. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/port_undef.inc +62 -0
  154. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.c +323 -0
  155. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.h +109 -0
  156. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/reflection.hpp +37 -0
  157. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table.c +926 -0
  158. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/table_internal.h +385 -0
  159. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test.proto +74 -0
  160. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.cc +186 -0
  161. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_cpp.proto +12 -0
  162. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_generated_code.cc +977 -0
  163. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/test_table.cc +580 -0
  164. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.c +472 -0
  165. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/text_encode.h +64 -0
  166. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.c +362 -0
  167. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.h +378 -0
  168. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb.hpp +115 -0
  169. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/upb_internal.h +68 -0
  170. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/BUILD +121 -0
  171. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/README.md +7 -0
  172. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.c +300 -0
  173. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare.h +66 -0
  174. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/compare_test.cc +236 -0
  175. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.c +572 -0
  176. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto.h +62 -0
  177. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_public_import_test.proto +32 -0
  178. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_regular_import_test.proto +36 -0
  179. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.cc +143 -0
  180. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_test.proto +119 -0
  181. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_weak_import_test.proto +28 -0
  182. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/def_to_proto_wweak_import_test.proto +28 -0
  183. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.c +311 -0
  184. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields.h +94 -0
  185. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.cc +202 -0
  186. data/ext/ruby_memprofiler_pprof/vendor/upb/upb/util/required_fields_test.proto +48 -0
  187. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/BUILD +78 -0
  188. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.cc +77 -0
  189. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/common.h +112 -0
  190. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upb.cc +1997 -0
  191. data/ext/ruby_memprofiler_pprof/vendor/upb/upbc/protoc-gen-upbdefs.cc +193 -0
  192. data/lib/ruby_memprofiler_pprof/atfork.rb +77 -0
  193. data/lib/ruby_memprofiler_pprof/block_flusher.rb +61 -0
  194. data/lib/ruby_memprofiler_pprof/file_flusher.rb +45 -0
  195. data/lib/ruby_memprofiler_pprof/profile_app.rb +30 -0
  196. data/lib/ruby_memprofiler_pprof/profile_data.rb +18 -0
  197. data/lib/ruby_memprofiler_pprof/version.rb +5 -0
  198. data/lib/ruby_memprofiler_pprof.rb +8 -0
  199. data/libexec/ruby_memprofiler_pprof_profile +16 -0
  200. metadata +257 -0
@@ -0,0 +1,1909 @@
1
+ /*
2
+ * Copyright (c) 2009-2021, Google LLC
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ * * Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * * Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * * Neither the name of Google LLC nor the
13
+ * names of its contributors may be used to endorse or promote products
14
+ * derived from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #include "python/message.h"
29
+
30
+ #include "python/convert.h"
31
+ #include "python/descriptor.h"
32
+ #include "python/extension_dict.h"
33
+ #include "python/map.h"
34
+ #include "python/repeated.h"
35
+ #include "upb/def.h"
36
+ #include "upb/reflection.h"
37
+ #include "upb/text_encode.h"
38
+ #include "upb/util/required_fields.h"
39
+
40
+ static const upb_MessageDef* PyUpb_MessageMeta_GetMsgdef(PyObject* cls);
41
+ static PyObject* PyUpb_MessageMeta_GetAttr(PyObject* self, PyObject* name);
42
+
43
+ // -----------------------------------------------------------------------------
44
+ // CPythonBits
45
+ // -----------------------------------------------------------------------------
46
+
47
+ // This struct contains a few things that are not exposed directly through the
48
+ // limited API, but that we can get at in somewhat more roundabout ways. The
49
+ // roundabout ways are slower, so we cache the values here.
50
+ //
51
+ // These values are valid to cache in a global, even across sub-interpreters,
52
+ // because they are not pointers to interpreter state. They are process
53
+ // globals that will be the same for any interpreter in this process.
54
+ typedef struct {
55
+ // For each member, we note the equivalent expression that we could use in the
56
+ // full (non-limited) API.
57
+ newfunc type_new; // PyTypeObject.tp_new
58
+ destructor type_dealloc; // PyTypeObject.tp_dealloc
59
+ getattrofunc type_getattro; // PyTypeObject.tp_getattro
60
+ setattrofunc type_setattro; // PyTypeObject.tp_setattro
61
+ size_t type_basicsize; // sizeof(PyHeapTypeObject)
62
+
63
+ // While we can refer to PY_VERSION_HEX in the limited API, this will give us
64
+ // the version of Python we were compiled against, which may be different
65
+ // than the version we are dynamically linked against. Here we want the
66
+ // version that is actually running in this process.
67
+ long python_version_hex; // PY_VERSION_HEX
68
+ } PyUpb_CPythonBits;
69
+
70
+ // A global containing the values for this process.
71
+ PyUpb_CPythonBits cpython_bits;
72
+
73
+ destructor upb_Pre310_PyType_GetDeallocSlot(PyTypeObject* type_subclass) {
74
+ // This is a bit desperate. We need type_dealloc(), but PyType_GetSlot(type,
75
+ // Py_tp_dealloc) will return subtype_dealloc(). There appears to be no way
76
+ // whatsoever to fetch type_dealloc() through the limited API until Python
77
+ // 3.10.
78
+ //
79
+ // To work around this so we attempt to find it by looking for the offset of
80
+ // tp_dealloc in PyTypeObject, then memcpy() it directly. This should always
81
+ // work in practice.
82
+ //
83
+ // Starting with Python 3.10 on you can call PyType_GetSlot() on non-heap
84
+ // types. We will be able to replace all this hack with just:
85
+ //
86
+ // PyType_GetSlot(&PyType_Type, Py_tp_dealloc)
87
+ //
88
+ destructor subtype_dealloc = PyType_GetSlot(type_subclass, Py_tp_dealloc);
89
+ for (size_t i = 0; i < 2000; i += sizeof(uintptr_t)) {
90
+ destructor maybe_subtype_dealloc;
91
+ memcpy(&maybe_subtype_dealloc, (char*)type_subclass + i,
92
+ sizeof(destructor));
93
+ if (maybe_subtype_dealloc == subtype_dealloc) {
94
+ destructor type_dealloc;
95
+ memcpy(&type_dealloc, (char*)&PyType_Type + i, sizeof(destructor));
96
+ return type_dealloc;
97
+ }
98
+ }
99
+ assert(false);
100
+ return NULL;
101
+ }
102
+
103
+ static bool PyUpb_CPythonBits_Init(PyUpb_CPythonBits* bits) {
104
+ PyObject* bases = NULL;
105
+ PyTypeObject* type = NULL;
106
+ PyObject* size = NULL;
107
+ PyObject* sys = NULL;
108
+ PyObject* hex_version = NULL;
109
+ bool ret = false;
110
+
111
+ // PyType_GetSlot() only works on heap types, so we cannot use it on
112
+ // &PyType_Type directly. Instead we create our own (temporary) type derived
113
+ // from PyType_Type: this will inherit all of the slots from PyType_Type, but
114
+ // as a heap type it can be queried with PyType_GetSlot().
115
+ static PyType_Slot dummy_slots[] = {{0, NULL}};
116
+
117
+ static PyType_Spec dummy_spec = {
118
+ "module.DummyClass", // tp_name
119
+ 0, // To be filled in by size of base // tp_basicsize
120
+ 0, // tp_itemsize
121
+ Py_TPFLAGS_DEFAULT, // tp_flags
122
+ dummy_slots,
123
+ };
124
+
125
+ bases = Py_BuildValue("(O)", &PyType_Type);
126
+ if (!bases) goto err;
127
+ type = (PyTypeObject*)PyType_FromSpecWithBases(&dummy_spec, bases);
128
+ if (!type) goto err;
129
+
130
+ bits->type_new = PyType_GetSlot(type, Py_tp_new);
131
+ bits->type_dealloc = upb_Pre310_PyType_GetDeallocSlot(type);
132
+ bits->type_getattro = PyType_GetSlot(type, Py_tp_getattro);
133
+ bits->type_setattro = PyType_GetSlot(type, Py_tp_setattro);
134
+
135
+ size = PyObject_GetAttrString((PyObject*)&PyType_Type, "__basicsize__");
136
+ if (!size) goto err;
137
+ bits->type_basicsize = PyLong_AsLong(size);
138
+ if (bits->type_basicsize == -1) goto err;
139
+
140
+ assert(bits->type_new);
141
+ assert(bits->type_dealloc);
142
+ assert(bits->type_getattro);
143
+ assert(bits->type_setattro);
144
+
145
+ #ifndef Py_LIMITED_API
146
+ assert(bits->type_new == PyType_Type.tp_new);
147
+ assert(bits->type_dealloc == PyType_Type.tp_dealloc);
148
+ assert(bits->type_getattro == PyType_Type.tp_getattro);
149
+ assert(bits->type_setattro == PyType_Type.tp_setattro);
150
+ assert(bits->type_basicsize == sizeof(PyHeapTypeObject));
151
+ #endif
152
+
153
+ sys = PyImport_ImportModule("sys");
154
+ hex_version = PyObject_GetAttrString(sys, "hexversion");
155
+ bits->python_version_hex = PyLong_AsLong(hex_version);
156
+ ret = true;
157
+
158
+ err:
159
+ Py_XDECREF(bases);
160
+ Py_XDECREF(type);
161
+ Py_XDECREF(size);
162
+ Py_XDECREF(sys);
163
+ Py_XDECREF(hex_version);
164
+ return ret;
165
+ }
166
+
167
+ // -----------------------------------------------------------------------------
168
+ // CMessage
169
+ // -----------------------------------------------------------------------------
170
+
171
+ // The main message object. The type of the object (PyUpb_CMessage.ob_type)
172
+ // will be an instance of the PyUpb_MessageMeta type (defined below). So the
173
+ // chain is:
174
+ // FooMessage = MessageMeta(...)
175
+ // foo = FooMessage()
176
+ //
177
+ // Which becomes:
178
+ // Object C Struct Type Python type (ob_type)
179
+ // ----------------- ----------------- ---------------------
180
+ // foo PyUpb_CMessage FooMessage
181
+ // FooMessage PyUpb_MessageMeta message_meta_type
182
+ // message_meta_type PyTypeObject 'type' in Python
183
+ //
184
+ // A message object can be in one of two states: present or non-present. When
185
+ // a message is non-present, it stores a reference to its parent, and a write
186
+ // to any attribute will trigger the message to become present in its parent.
187
+ // The parent may also be non-present, in which case a mutation will trigger a
188
+ // chain reaction.
189
+ typedef struct PyUpb_CMessage {
190
+ PyObject_HEAD;
191
+ PyObject* arena;
192
+ uintptr_t def; // Tagged, low bit 1 == upb_FieldDef*, else upb_MessageDef*
193
+ union {
194
+ // when def is msgdef, the data for this msg.
195
+ upb_Message* msg;
196
+ // when def is fielddef, owning pointer to parent
197
+ struct PyUpb_CMessage* parent;
198
+ } ptr;
199
+ PyObject* ext_dict; // Weak pointer to extension dict, if any.
200
+ // name->obj dict for non-present msg/map/repeated, NULL if none.
201
+ PyUpb_WeakMap* unset_subobj_map;
202
+ int version;
203
+ } PyUpb_CMessage;
204
+
205
+ static PyObject* PyUpb_CMessage_GetAttr(PyObject* _self, PyObject* attr);
206
+
207
+ bool PyUpb_CMessage_IsStub(PyUpb_CMessage* msg) { return msg->def & 1; }
208
+
209
+ const upb_FieldDef* PyUpb_CMessage_GetFieldDef(PyUpb_CMessage* msg) {
210
+ assert(PyUpb_CMessage_IsStub(msg));
211
+ return (void*)(msg->def & ~(uintptr_t)1);
212
+ }
213
+
214
+ static const upb_MessageDef* _PyUpb_CMessage_GetMsgdef(PyUpb_CMessage* msg) {
215
+ return PyUpb_CMessage_IsStub(msg)
216
+ ? upb_FieldDef_MessageSubDef(PyUpb_CMessage_GetFieldDef(msg))
217
+ : (void*)msg->def;
218
+ }
219
+
220
+ const upb_MessageDef* PyUpb_CMessage_GetMsgdef(PyObject* self) {
221
+ return _PyUpb_CMessage_GetMsgdef((PyUpb_CMessage*)self);
222
+ }
223
+
224
+ static upb_Message* PyUpb_CMessage_GetMsg(PyUpb_CMessage* self) {
225
+ assert(!PyUpb_CMessage_IsStub(self));
226
+ return self->ptr.msg;
227
+ }
228
+
229
+ bool PyUpb_CMessage_TryCheck(PyObject* self) {
230
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
231
+ PyObject* type = (PyObject*)Py_TYPE(self);
232
+ return Py_TYPE(type) == state->message_meta_type;
233
+ }
234
+
235
+ bool PyUpb_CMessage_Verify(PyObject* self) {
236
+ if (!PyUpb_CMessage_TryCheck(self)) {
237
+ PyErr_Format(PyExc_TypeError, "Expected a message object, but got %R.",
238
+ self);
239
+ return false;
240
+ }
241
+ return true;
242
+ }
243
+
244
+ // If the message is reified, returns it. Otherwise, returns NULL.
245
+ // If NULL is returned, the object is empty and has no underlying data.
246
+ upb_Message* PyUpb_CMessage_GetIfReified(PyObject* _self) {
247
+ PyUpb_CMessage* self = (void*)_self;
248
+ return PyUpb_CMessage_IsStub(self) ? NULL : self->ptr.msg;
249
+ }
250
+
251
+ static PyObject* PyUpb_CMessage_New(PyObject* cls, PyObject* unused_args,
252
+ PyObject* unused_kwargs) {
253
+ const upb_MessageDef* msgdef = PyUpb_MessageMeta_GetMsgdef(cls);
254
+ PyUpb_CMessage* msg = (void*)PyType_GenericAlloc((PyTypeObject*)cls, 0);
255
+ msg->def = (uintptr_t)msgdef;
256
+ msg->arena = PyUpb_Arena_New();
257
+ msg->ptr.msg = upb_Message_New(msgdef, PyUpb_Arena_Get(msg->arena));
258
+ msg->unset_subobj_map = NULL;
259
+ msg->ext_dict = NULL;
260
+ msg->version = 0;
261
+
262
+ PyObject* ret = &msg->ob_base;
263
+ PyUpb_ObjCache_Add(msg->ptr.msg, ret);
264
+ return ret;
265
+ }
266
+
267
+ /*
268
+ * PyUpb_CMessage_LookupName()
269
+ *
270
+ * Tries to find a field or oneof named `py_name` in the message object `self`.
271
+ * The user must pass `f` and/or `o` to indicate whether a field or a oneof name
272
+ * is expected. If the name is found and it has an expected type, the function
273
+ * sets `*f` or `*o` respectively and returns true. Otherwise returns false
274
+ * and sets an exception of type `exc_type` if provided.
275
+ */
276
+ static bool PyUpb_CMessage_LookupName(PyUpb_CMessage* self, PyObject* py_name,
277
+ const upb_FieldDef** f,
278
+ const upb_OneofDef** o,
279
+ PyObject* exc_type) {
280
+ assert(f || o);
281
+ Py_ssize_t size;
282
+ const char* name = NULL;
283
+ if (PyUnicode_Check(py_name)) {
284
+ name = PyUnicode_AsUTF8AndSize(py_name, &size);
285
+ } else if (PyBytes_Check(py_name)) {
286
+ PyBytes_AsStringAndSize(py_name, (char**)&name, &size);
287
+ }
288
+ if (!name) {
289
+ PyErr_Format(exc_type,
290
+ "Expected a field name, but got non-string argument %S.",
291
+ py_name);
292
+ return false;
293
+ }
294
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
295
+
296
+ if (!upb_MessageDef_FindByNameWithSize(msgdef, name, size, f, o)) {
297
+ if (exc_type) {
298
+ PyErr_Format(exc_type, "Protocol message %s has no \"%s\" field.",
299
+ upb_MessageDef_Name(msgdef), name);
300
+ }
301
+ return false;
302
+ }
303
+
304
+ if (!o && !*f) {
305
+ if (exc_type) {
306
+ PyErr_Format(exc_type, "Expected a field name, but got oneof name %s.",
307
+ name);
308
+ }
309
+ return false;
310
+ }
311
+
312
+ if (!f && !*o) {
313
+ if (exc_type) {
314
+ PyErr_Format(exc_type, "Expected a oneof name, but got field name %s.",
315
+ name);
316
+ }
317
+ return false;
318
+ }
319
+
320
+ return true;
321
+ }
322
+
323
+ static bool PyUpb_CMessage_InitMessageMapEntry(PyObject* dst, PyObject* src) {
324
+ if (!src || !dst) return false;
325
+
326
+ // TODO(haberman): Currently we are doing Clear()+MergeFrom(). Replace with
327
+ // CopyFrom() once that is implemented.
328
+ PyObject* ok = PyObject_CallMethod(dst, "Clear", NULL);
329
+ if (!ok) return false;
330
+ Py_DECREF(ok);
331
+ ok = PyObject_CallMethod(dst, "MergeFrom", "O", src);
332
+ if (!ok) return false;
333
+ Py_DECREF(ok);
334
+
335
+ return true;
336
+ }
337
+
338
+ int PyUpb_CMessage_InitMapAttributes(PyObject* map, PyObject* value,
339
+ const upb_FieldDef* f) {
340
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
341
+ const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
342
+ PyObject* it = NULL;
343
+ PyObject* tmp = NULL;
344
+ int ret = -1;
345
+ if (upb_FieldDef_IsSubMessage(val_f)) {
346
+ it = PyObject_GetIter(value);
347
+ if (it == NULL) {
348
+ PyErr_Format(PyExc_TypeError, "Argument for field %s is not iterable",
349
+ upb_FieldDef_FullName(f));
350
+ goto err;
351
+ }
352
+ PyObject* e;
353
+ while ((e = PyIter_Next(it)) != NULL) {
354
+ PyObject* src = PyObject_GetItem(value, e);
355
+ PyObject* dst = PyObject_GetItem(map, e);
356
+ Py_DECREF(e);
357
+ bool ok = PyUpb_CMessage_InitMessageMapEntry(dst, src);
358
+ Py_XDECREF(src);
359
+ Py_XDECREF(dst);
360
+ if (!ok) goto err;
361
+ }
362
+ } else {
363
+ tmp = PyObject_CallMethod(map, "update", "O", value);
364
+ if (!tmp) goto err;
365
+ }
366
+ ret = 0;
367
+
368
+ err:
369
+ Py_XDECREF(it);
370
+ Py_XDECREF(tmp);
371
+ return ret;
372
+ }
373
+
374
+ void PyUpb_CMessage_EnsureReified(PyUpb_CMessage* self);
375
+
376
+ static bool PyUpb_CMessage_InitMapAttribute(PyObject* _self, PyObject* name,
377
+ const upb_FieldDef* f,
378
+ PyObject* value) {
379
+ PyObject* map = PyUpb_CMessage_GetAttr(_self, name);
380
+ int ok = PyUpb_CMessage_InitMapAttributes(map, value, f);
381
+ Py_DECREF(map);
382
+ return ok >= 0;
383
+ }
384
+
385
+ static bool PyUpb_CMessage_InitRepeatedMessageAttribute(PyObject* _self,
386
+ PyObject* repeated,
387
+ PyObject* value,
388
+ const upb_FieldDef* f) {
389
+ PyObject* it = PyObject_GetIter(value);
390
+ if (!it) {
391
+ PyErr_Format(PyExc_TypeError, "Argument for field %s is not iterable",
392
+ upb_FieldDef_FullName(f));
393
+ return false;
394
+ }
395
+ PyObject* e = NULL;
396
+ PyObject* m = NULL;
397
+ while ((e = PyIter_Next(it)) != NULL) {
398
+ if (PyDict_Check(e)) {
399
+ m = PyUpb_RepeatedCompositeContainer_Add(repeated, NULL, e);
400
+ if (!m) goto err;
401
+ } else {
402
+ m = PyUpb_RepeatedCompositeContainer_Add(repeated, NULL, NULL);
403
+ if (!m) goto err;
404
+ PyObject* merged = PyUpb_CMessage_MergeFrom(m, e);
405
+ if (!merged) goto err;
406
+ Py_DECREF(merged);
407
+ }
408
+ Py_DECREF(e);
409
+ Py_DECREF(m);
410
+ m = NULL;
411
+ }
412
+
413
+ err:
414
+ Py_XDECREF(it);
415
+ Py_XDECREF(e);
416
+ Py_XDECREF(m);
417
+ return !PyErr_Occurred(); // Check PyIter_Next() exit.
418
+ }
419
+
420
+ static bool PyUpb_CMessage_InitRepeatedAttribute(PyObject* _self,
421
+ PyObject* name,
422
+ PyObject* value) {
423
+ PyUpb_CMessage* self = (void*)_self;
424
+ const upb_FieldDef* field;
425
+ if (!PyUpb_CMessage_LookupName(self, name, &field, NULL,
426
+ PyExc_AttributeError)) {
427
+ return false;
428
+ }
429
+ bool ok = false;
430
+ PyObject* repeated = PyUpb_CMessage_GetFieldValue(_self, field);
431
+ PyObject* tmp = NULL;
432
+ if (!repeated) goto err;
433
+ if (upb_FieldDef_IsSubMessage(field)) {
434
+ if (!PyUpb_CMessage_InitRepeatedMessageAttribute(_self, repeated, value,
435
+ field)) {
436
+ goto err;
437
+ }
438
+ } else {
439
+ tmp = PyUpb_RepeatedContainer_Extend(repeated, value);
440
+ if (!tmp) goto err;
441
+ }
442
+ ok = true;
443
+
444
+ err:
445
+ Py_XDECREF(repeated);
446
+ Py_XDECREF(tmp);
447
+ return ok;
448
+ }
449
+
450
+ static bool PyUpb_CMessage_InitMessageAttribute(PyObject* _self, PyObject* name,
451
+ PyObject* value) {
452
+ PyObject* submsg = PyUpb_CMessage_GetAttr(_self, name);
453
+ if (!submsg) return -1;
454
+ assert(!PyErr_Occurred());
455
+ bool ok;
456
+ if (PyUpb_CMessage_TryCheck(value)) {
457
+ PyObject* tmp = PyUpb_CMessage_MergeFrom(submsg, value);
458
+ ok = tmp != NULL;
459
+ Py_DECREF(tmp);
460
+ } else if (PyDict_Check(value)) {
461
+ assert(!PyErr_Occurred());
462
+ ok = PyUpb_CMessage_InitAttributes(submsg, NULL, value) >= 0;
463
+ } else {
464
+ const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(_self);
465
+ PyErr_Format(PyExc_TypeError, "Message must be initialized with a dict: %s",
466
+ upb_MessageDef_FullName(m));
467
+ ok = false;
468
+ }
469
+ Py_DECREF(submsg);
470
+ return ok;
471
+ }
472
+
473
+ static bool PyUpb_CMessage_InitScalarAttribute(upb_Message* msg,
474
+ const upb_FieldDef* f,
475
+ PyObject* value,
476
+ upb_Arena* arena) {
477
+ upb_MessageValue msgval;
478
+ assert(!PyErr_Occurred());
479
+ if (!PyUpb_PyToUpb(value, f, &msgval, arena)) return false;
480
+ upb_Message_Set(msg, f, msgval, arena);
481
+ return true;
482
+ }
483
+
484
+ int PyUpb_CMessage_InitAttributes(PyObject* _self, PyObject* args,
485
+ PyObject* kwargs) {
486
+ assert(!PyErr_Occurred());
487
+
488
+ if (args != NULL && PyTuple_Size(args) != 0) {
489
+ PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
490
+ return -1;
491
+ }
492
+
493
+ if (kwargs == NULL) return 0;
494
+
495
+ PyUpb_CMessage* self = (void*)_self;
496
+ Py_ssize_t pos = 0;
497
+ PyObject* name;
498
+ PyObject* value;
499
+ PyUpb_CMessage_EnsureReified(self);
500
+ upb_Message* msg = PyUpb_CMessage_GetMsg(self);
501
+ upb_Arena* arena = PyUpb_Arena_Get(self->arena);
502
+
503
+ while (PyDict_Next(kwargs, &pos, &name, &value)) {
504
+ assert(!PyErr_Occurred());
505
+ const upb_FieldDef* f;
506
+ assert(!PyErr_Occurred());
507
+ if (!PyUpb_CMessage_LookupName(self, name, &f, NULL, PyExc_ValueError)) {
508
+ return -1;
509
+ }
510
+
511
+ if (value == Py_None) continue; // Ignored.
512
+
513
+ assert(!PyErr_Occurred());
514
+
515
+ if (upb_FieldDef_IsMap(f)) {
516
+ if (!PyUpb_CMessage_InitMapAttribute(_self, name, f, value)) return -1;
517
+ } else if (upb_FieldDef_IsRepeated(f)) {
518
+ if (!PyUpb_CMessage_InitRepeatedAttribute(_self, name, value)) return -1;
519
+ } else if (upb_FieldDef_IsSubMessage(f)) {
520
+ if (!PyUpb_CMessage_InitMessageAttribute(_self, name, value)) return -1;
521
+ } else {
522
+ if (!PyUpb_CMessage_InitScalarAttribute(msg, f, value, arena)) return -1;
523
+ }
524
+ if (PyErr_Occurred()) return -1;
525
+ }
526
+
527
+ if (PyErr_Occurred()) return -1;
528
+ return 0;
529
+ }
530
+
531
+ static int PyUpb_CMessage_Init(PyObject* _self, PyObject* args,
532
+ PyObject* kwargs) {
533
+ if (args != NULL && PyTuple_Size(args) != 0) {
534
+ PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
535
+ return -1;
536
+ }
537
+
538
+ return PyUpb_CMessage_InitAttributes(_self, args, kwargs);
539
+ }
540
+
541
+ static PyObject* PyUpb_CMessage_NewStub(PyObject* parent, const upb_FieldDef* f,
542
+ PyObject* arena) {
543
+ const upb_MessageDef* sub_m = upb_FieldDef_MessageSubDef(f);
544
+ PyObject* cls = PyUpb_Descriptor_GetClass(sub_m);
545
+
546
+ PyUpb_CMessage* msg = (void*)PyType_GenericAlloc((PyTypeObject*)cls, 0);
547
+ msg->def = (uintptr_t)f | 1;
548
+ msg->arena = arena;
549
+ msg->ptr.parent = (PyUpb_CMessage*)parent;
550
+ msg->unset_subobj_map = NULL;
551
+ msg->ext_dict = NULL;
552
+ msg->version = 0;
553
+
554
+ Py_DECREF(cls);
555
+ Py_INCREF(parent);
556
+ Py_INCREF(arena);
557
+ return &msg->ob_base;
558
+ }
559
+
560
+ static bool PyUpb_CMessage_IsEqual(PyUpb_CMessage* m1, PyObject* _m2) {
561
+ PyUpb_CMessage* m2 = (void*)_m2;
562
+ if (m1 == m2) return true;
563
+ if (!PyObject_TypeCheck(_m2, m1->ob_base.ob_type)) {
564
+ return false;
565
+ }
566
+ const upb_MessageDef* m1_msgdef = _PyUpb_CMessage_GetMsgdef(m1);
567
+ #ifndef NDEBUG
568
+ const upb_MessageDef* m2_msgdef = _PyUpb_CMessage_GetMsgdef(m2);
569
+ assert(m1_msgdef == m2_msgdef);
570
+ #endif
571
+ const upb_Message* m1_msg = PyUpb_CMessage_GetIfReified((PyObject*)m1);
572
+ const upb_Message* m2_msg = PyUpb_CMessage_GetIfReified(_m2);
573
+ return PyUpb_Message_IsEqual(m1_msg, m2_msg, m1_msgdef);
574
+ }
575
+
576
+ static const upb_FieldDef* PyUpb_CMessage_InitAsMsg(PyUpb_CMessage* m,
577
+ upb_Arena* arena) {
578
+ const upb_FieldDef* f = PyUpb_CMessage_GetFieldDef(m);
579
+ m->ptr.msg = upb_Message_New(upb_FieldDef_MessageSubDef(f), arena);
580
+ m->def = (uintptr_t)upb_FieldDef_MessageSubDef(f);
581
+ PyUpb_ObjCache_Add(m->ptr.msg, &m->ob_base);
582
+ return f;
583
+ }
584
+
585
+ static void PyUpb_CMessage_SetField(PyUpb_CMessage* parent,
586
+ const upb_FieldDef* f,
587
+ PyUpb_CMessage* child, upb_Arena* arena) {
588
+ upb_MessageValue msgval = {.msg_val = PyUpb_CMessage_GetMsg(child)};
589
+ upb_Message_Set(PyUpb_CMessage_GetMsg(parent), f, msgval, arena);
590
+ PyUpb_WeakMap_Delete(parent->unset_subobj_map, f);
591
+ // Releases a ref previously owned by child->ptr.parent of our child.
592
+ Py_DECREF(child);
593
+ }
594
+
595
+ /*
596
+ * PyUpb_CMessage_EnsureReified()
597
+ *
598
+ * This implements the "expando" behavior of Python protos:
599
+ * foo = FooProto()
600
+ *
601
+ * # The intermediate messages don't really exist, and won't be serialized.
602
+ * x = foo.bar.bar.bar.bar.bar.baz
603
+ *
604
+ * # Now all the intermediate objects are created.
605
+ * foo.bar.bar.bar.bar.bar.baz = 5
606
+ *
607
+ * This function should be called before performing any mutation of a protobuf
608
+ * object.
609
+ *
610
+ * Post-condition:
611
+ * PyUpb_CMessage_IsStub(self) is false
612
+ */
613
+ void PyUpb_CMessage_EnsureReified(PyUpb_CMessage* self) {
614
+ if (!PyUpb_CMessage_IsStub(self)) return;
615
+ upb_Arena* arena = PyUpb_Arena_Get(self->arena);
616
+
617
+ // This is a non-present message. We need to create a real upb_Message for
618
+ // this object and every parent until we reach a present message.
619
+ PyUpb_CMessage* child = self;
620
+ PyUpb_CMessage* parent = self->ptr.parent;
621
+ const upb_FieldDef* child_f = PyUpb_CMessage_InitAsMsg(child, arena);
622
+ Py_INCREF(child); // To avoid a special-case in PyUpb_CMessage_SetField().
623
+
624
+ do {
625
+ PyUpb_CMessage* next_parent = parent->ptr.parent;
626
+ const upb_FieldDef* parent_f = NULL;
627
+ if (PyUpb_CMessage_IsStub(parent)) {
628
+ parent_f = PyUpb_CMessage_InitAsMsg(parent, arena);
629
+ }
630
+ PyUpb_CMessage_SetField(parent, child_f, child, arena);
631
+ child = parent;
632
+ child_f = parent_f;
633
+ parent = next_parent;
634
+ } while (child_f);
635
+
636
+ // Releases ref previously owned by child->ptr.parent of our child.
637
+ Py_DECREF(child);
638
+ self->version++;
639
+ }
640
+
641
+ static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self);
642
+
643
+ /*
644
+ * PyUpb_CMessage_Reify()
645
+ *
646
+ * The message equivalent of PyUpb_*Container_Reify(), this transitions
647
+ * the wrapper from the unset state (owning a reference on self->ptr.parent) to
648
+ * the set state (having a non-owning pointer to self->ptr.msg).
649
+ */
650
+ static void PyUpb_CMessage_Reify(PyUpb_CMessage* self, const upb_FieldDef* f,
651
+ upb_Message* msg) {
652
+ assert(f == PyUpb_CMessage_GetFieldDef(self));
653
+ if (!msg) {
654
+ const upb_MessageDef* msgdef = PyUpb_CMessage_GetMsgdef((PyObject*)self);
655
+ msg = upb_Message_New(msgdef, PyUpb_Arena_Get(self->arena));
656
+ }
657
+ PyUpb_ObjCache_Add(msg, &self->ob_base);
658
+ Py_DECREF(&self->ptr.parent->ob_base);
659
+ self->ptr.msg = msg; // Overwrites self->ptr.parent
660
+ self->def = (uintptr_t)upb_FieldDef_MessageSubDef(f);
661
+ PyUpb_CMessage_SyncSubobjs(self);
662
+ }
663
+
664
+ /*
665
+ * PyUpb_CMessage_SyncSubobjs()
666
+ *
667
+ * This operation must be invoked whenever the underlying upb_Message has been
668
+ * mutated directly in C. This will attach any newly-present field data
669
+ * to previously returned stub wrapper objects.
670
+ *
671
+ * For example:
672
+ * foo = FooMessage()
673
+ * sub = foo.submsg # Empty, unset sub-message
674
+ *
675
+ * # SyncSubobjs() is required to connect our existing 'sub' wrapper to the
676
+ * # newly created foo.submsg data in C.
677
+ * foo.MergeFrom(FooMessage(submsg={}))
678
+ *
679
+ * This requires that all of the new sub-objects that have appeared are owned
680
+ * by `self`'s arena.
681
+ */
682
+ static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self) {
683
+ PyUpb_WeakMap* subobj_map = self->unset_subobj_map;
684
+ if (!subobj_map) return;
685
+
686
+ upb_Message* msg = PyUpb_CMessage_GetMsg(self);
687
+ intptr_t iter = PYUPB_WEAKMAP_BEGIN;
688
+ const void* key;
689
+ PyObject* obj;
690
+
691
+ // The last ref to this message could disappear during iteration.
692
+ // When we call PyUpb_*Container_Reify() below, the container will drop
693
+ // its ref on `self`. If that was the last ref on self, the object will be
694
+ // deleted, and `subobj_map` along with it. We need it to live until we are
695
+ // done iterating.
696
+ Py_INCREF(&self->ob_base);
697
+
698
+ while (PyUpb_WeakMap_Next(subobj_map, &key, &obj, &iter)) {
699
+ const upb_FieldDef* f = key;
700
+ if (upb_FieldDef_HasPresence(f) && !upb_Message_Has(msg, f)) continue;
701
+ upb_MessageValue msgval = upb_Message_Get(msg, f);
702
+ PyUpb_WeakMap_DeleteIter(subobj_map, &iter);
703
+ if (upb_FieldDef_IsMap(f)) {
704
+ if (!msgval.map_val) continue;
705
+ PyUpb_MapContainer_Reify(obj, (upb_Map*)msgval.map_val);
706
+ } else if (upb_FieldDef_IsRepeated(f)) {
707
+ if (!msgval.array_val) continue;
708
+ PyUpb_RepeatedContainer_Reify(obj, (upb_Array*)msgval.array_val);
709
+ } else {
710
+ PyUpb_CMessage* sub = (void*)obj;
711
+ assert(self == sub->ptr.parent);
712
+ PyUpb_CMessage_Reify(sub, f, (upb_Message*)msgval.msg_val);
713
+ }
714
+ }
715
+
716
+ Py_DECREF(&self->ob_base);
717
+
718
+ // TODO(haberman): present fields need to be iterated too if they can reach
719
+ // a WeakMap.
720
+ }
721
+
722
+ static PyObject* PyUpb_CMessage_ToString(PyUpb_CMessage* self) {
723
+ if (PyUpb_CMessage_IsStub(self)) {
724
+ return PyUnicode_FromStringAndSize(NULL, 0);
725
+ }
726
+ upb_Message* msg = PyUpb_CMessage_GetMsg(self);
727
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
728
+ const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(msgdef));
729
+ char buf[1024];
730
+ int options = UPB_TXTENC_SKIPUNKNOWN;
731
+ size_t size = upb_TextEncode(msg, msgdef, symtab, options, buf, sizeof(buf));
732
+ if (size < sizeof(buf)) {
733
+ return PyUnicode_FromStringAndSize(buf, size);
734
+ } else {
735
+ char* buf2 = malloc(size + 1);
736
+ size_t size2 = upb_TextEncode(msg, msgdef, symtab, options, buf2, size + 1);
737
+ assert(size == size2);
738
+ PyObject* ret = PyUnicode_FromStringAndSize(buf2, size2);
739
+ free(buf2);
740
+ return ret;
741
+ }
742
+ }
743
+
744
+ static PyObject* PyUpb_CMessage_RichCompare(PyObject* _self, PyObject* other,
745
+ int opid) {
746
+ PyUpb_CMessage* self = (void*)_self;
747
+ if (opid != Py_EQ && opid != Py_NE) {
748
+ Py_INCREF(Py_NotImplemented);
749
+ return Py_NotImplemented;
750
+ }
751
+ bool ret = PyUpb_CMessage_IsEqual(self, other);
752
+ if (opid == Py_NE) ret = !ret;
753
+ return PyBool_FromLong(ret);
754
+ }
755
+
756
+ void PyUpb_CMessage_CacheDelete(PyObject* _self, const upb_FieldDef* f) {
757
+ PyUpb_CMessage* self = (void*)_self;
758
+ PyUpb_WeakMap_Delete(self->unset_subobj_map, f);
759
+ }
760
+
761
+ void PyUpb_CMessage_SetConcreteSubobj(PyObject* _self, const upb_FieldDef* f,
762
+ upb_MessageValue subobj) {
763
+ PyUpb_CMessage* self = (void*)_self;
764
+ PyUpb_CMessage_EnsureReified(self);
765
+ PyUpb_CMessage_CacheDelete(_self, f);
766
+ upb_Message_Set(self->ptr.msg, f, subobj, PyUpb_Arena_Get(self->arena));
767
+ }
768
+
769
+ static void PyUpb_CMessage_Dealloc(PyObject* _self) {
770
+ PyUpb_CMessage* self = (void*)_self;
771
+
772
+ if (PyUpb_CMessage_IsStub(self)) {
773
+ PyUpb_CMessage_CacheDelete((PyObject*)self->ptr.parent,
774
+ PyUpb_CMessage_GetFieldDef(self));
775
+ Py_DECREF(self->ptr.parent);
776
+ } else {
777
+ PyUpb_ObjCache_Delete(self->ptr.msg);
778
+ }
779
+
780
+ if (self->unset_subobj_map) {
781
+ PyUpb_WeakMap_Free(self->unset_subobj_map);
782
+ }
783
+
784
+ Py_DECREF(self->arena);
785
+
786
+ // We do not use PyUpb_Dealloc() here because CMessage is a base type and for
787
+ // base types there is a bug we have to work around in this case (see below).
788
+ PyTypeObject* tp = Py_TYPE(self);
789
+ freefunc tp_free = PyType_GetSlot(tp, Py_tp_free);
790
+ tp_free(self);
791
+
792
+ if (cpython_bits.python_version_hex >= 0x03080000) {
793
+ // Prior to Python 3.8 there is a bug where deallocating the type here would
794
+ // lead to a double-decref: https://bugs.python.org/issue37879
795
+ Py_DECREF(tp);
796
+ }
797
+ }
798
+
799
+ PyObject* PyUpb_CMessage_Get(upb_Message* u_msg, const upb_MessageDef* m,
800
+ PyObject* arena) {
801
+ PyObject* ret = PyUpb_ObjCache_Get(u_msg);
802
+ if (ret) return ret;
803
+
804
+ PyObject* cls = PyUpb_Descriptor_GetClass(m);
805
+ // It is not safe to use PyObject_{,GC}_New() due to:
806
+ // https://bugs.python.org/issue35810
807
+ PyUpb_CMessage* py_msg = (void*)PyType_GenericAlloc((PyTypeObject*)cls, 0);
808
+ py_msg->arena = arena;
809
+ py_msg->def = (uintptr_t)m;
810
+ py_msg->ptr.msg = u_msg;
811
+ py_msg->unset_subobj_map = NULL;
812
+ py_msg->ext_dict = NULL;
813
+ py_msg->version = 0;
814
+ ret = &py_msg->ob_base;
815
+ Py_DECREF(cls);
816
+ Py_INCREF(arena);
817
+ PyUpb_ObjCache_Add(u_msg, ret);
818
+ return ret;
819
+ }
820
+
821
+ /* PyUpb_CMessage_GetStub()
822
+ *
823
+ * Non-present messages return "stub" objects that point to their parent, but
824
+ * will materialize into real upb objects if they are mutated.
825
+ *
826
+ * Note: we do *not* create stubs for repeated/map fields unless the parent
827
+ * is a stub:
828
+ *
829
+ * msg = TestMessage()
830
+ * msg.submessage # (A) Creates a stub
831
+ * msg.repeated_foo # (B) Does *not* create a stub
832
+ * msg.submessage.repeated_bar # (C) Creates a stub
833
+ *
834
+ * In case (B) we have some freedom: we could either create a stub, or create
835
+ * a reified object with underlying data. It appears that either could work
836
+ * equally well, with no observable change to users. There isn't a clear
837
+ * advantage to either choice. We choose to follow the behavior of the
838
+ * pre-existing C++ behavior for consistency, but if it becomes apparent that
839
+ * there would be some benefit to reversing this decision, it should be totally
840
+ * within the realm of possibility.
841
+ */
842
+ PyObject* PyUpb_CMessage_GetStub(PyUpb_CMessage* self,
843
+ const upb_FieldDef* field) {
844
+ PyObject* _self = (void*)self;
845
+ if (!self->unset_subobj_map) {
846
+ self->unset_subobj_map = PyUpb_WeakMap_New();
847
+ }
848
+ PyObject* subobj = PyUpb_WeakMap_Get(self->unset_subobj_map, field);
849
+
850
+ if (subobj) return subobj;
851
+
852
+ if (upb_FieldDef_IsMap(field)) {
853
+ subobj = PyUpb_MapContainer_NewStub(_self, field, self->arena);
854
+ } else if (upb_FieldDef_IsRepeated(field)) {
855
+ subobj = PyUpb_RepeatedContainer_NewStub(_self, field, self->arena);
856
+ } else {
857
+ subobj = PyUpb_CMessage_NewStub(&self->ob_base, field, self->arena);
858
+ }
859
+ PyUpb_WeakMap_Add(self->unset_subobj_map, field, subobj);
860
+
861
+ assert(!PyErr_Occurred());
862
+ return subobj;
863
+ }
864
+
865
+ PyObject* PyUpb_CMessage_GetPresentWrapper(PyUpb_CMessage* self,
866
+ const upb_FieldDef* field) {
867
+ assert(!PyUpb_CMessage_IsStub(self));
868
+ upb_MutableMessageValue mutval =
869
+ upb_Message_Mutable(self->ptr.msg, field, PyUpb_Arena_Get(self->arena));
870
+ if (upb_FieldDef_IsMap(field)) {
871
+ return PyUpb_MapContainer_GetOrCreateWrapper(mutval.map, field,
872
+ self->arena);
873
+ } else {
874
+ return PyUpb_RepeatedContainer_GetOrCreateWrapper(mutval.array, field,
875
+ self->arena);
876
+ }
877
+ }
878
+
879
+ PyObject* PyUpb_CMessage_GetScalarValue(PyUpb_CMessage* self,
880
+ const upb_FieldDef* field) {
881
+ upb_MessageValue val;
882
+ if (PyUpb_CMessage_IsStub(self)) {
883
+ // Unset message always returns default values.
884
+ val = upb_FieldDef_Default(field);
885
+ } else {
886
+ val = upb_Message_Get(self->ptr.msg, field);
887
+ }
888
+ return PyUpb_UpbToPy(val, field, self->arena);
889
+ }
890
+
891
+ /*
892
+ * PyUpb_CMessage_GetFieldValue()
893
+ *
894
+ * Implements the equivalent of getattr(msg, field), once `field` has
895
+ * already been resolved to a `upb_FieldDef*`.
896
+ *
897
+ * This may involve constructing a wrapper object for the given field, or
898
+ * returning one that was previously constructed. If the field is not actually
899
+ * set, the wrapper object will be an "unset" object that is not actually
900
+ * connected to any C data.
901
+ */
902
+ PyObject* PyUpb_CMessage_GetFieldValue(PyObject* _self,
903
+ const upb_FieldDef* field) {
904
+ PyUpb_CMessage* self = (void*)_self;
905
+ assert(upb_FieldDef_ContainingType(field) == PyUpb_CMessage_GetMsgdef(_self));
906
+ bool submsg = upb_FieldDef_IsSubMessage(field);
907
+ bool seq = upb_FieldDef_IsRepeated(field);
908
+
909
+ if ((PyUpb_CMessage_IsStub(self) && (submsg || seq)) ||
910
+ (submsg && !seq && !upb_Message_Has(self->ptr.msg, field))) {
911
+ return PyUpb_CMessage_GetStub(self, field);
912
+ } else if (seq) {
913
+ return PyUpb_CMessage_GetPresentWrapper(self, field);
914
+ } else {
915
+ return PyUpb_CMessage_GetScalarValue(self, field);
916
+ }
917
+ }
918
+
919
+ int PyUpb_CMessage_SetFieldValue(PyObject* _self, const upb_FieldDef* field,
920
+ PyObject* value, PyObject* exc) {
921
+ PyUpb_CMessage* self = (void*)_self;
922
+ assert(value);
923
+
924
+ if (upb_FieldDef_IsSubMessage(field) || upb_FieldDef_IsRepeated(field)) {
925
+ PyErr_Format(exc,
926
+ "Assignment not allowed to message, map, or repeated "
927
+ "field \"%s\" in protocol message object.",
928
+ upb_FieldDef_Name(field));
929
+ return -1;
930
+ }
931
+
932
+ PyUpb_CMessage_EnsureReified(self);
933
+
934
+ upb_MessageValue val;
935
+ upb_Arena* arena = PyUpb_Arena_Get(self->arena);
936
+ if (!PyUpb_PyToUpb(value, field, &val, arena)) {
937
+ return -1;
938
+ }
939
+
940
+ upb_Message_Set(self->ptr.msg, field, val, arena);
941
+ return 0;
942
+ }
943
+
944
+ int PyUpb_CMessage_GetVersion(PyObject* _self) {
945
+ PyUpb_CMessage* self = (void*)_self;
946
+ return self->version;
947
+ }
948
+
949
+ /*
950
+ * PyUpb_CMessage_GetAttr()
951
+ *
952
+ * Implements:
953
+ * foo = msg.foo
954
+ *
955
+ * Attribute lookup must find both message fields and base class methods like
956
+ * msg.SerializeToString().
957
+ */
958
+ __attribute__((flatten)) static PyObject* PyUpb_CMessage_GetAttr(
959
+ PyObject* _self, PyObject* attr) {
960
+ PyUpb_CMessage* self = (void*)_self;
961
+
962
+ // Lookup field by name.
963
+ const upb_FieldDef* field;
964
+ if (PyUpb_CMessage_LookupName(self, attr, &field, NULL, NULL)) {
965
+ return PyUpb_CMessage_GetFieldValue(_self, field);
966
+ }
967
+
968
+ // Check base class attributes.
969
+ assert(!PyErr_Occurred());
970
+ PyObject* ret = PyObject_GenericGetAttr(_self, attr);
971
+ if (ret) return ret;
972
+
973
+ // Swallow AttributeError if it occurred and try again on the metaclass
974
+ // to pick up class attributes. But we have to special-case "Extensions"
975
+ // which affirmatively returns AttributeError when a message is not
976
+ // extendable.
977
+ const char* name;
978
+ if (PyErr_ExceptionMatches(PyExc_AttributeError) &&
979
+ (name = PyUpb_GetStrData(attr)) && strcmp(name, "Extensions") != 0) {
980
+ PyErr_Clear();
981
+ return PyUpb_MessageMeta_GetAttr((PyObject*)Py_TYPE(_self), attr);
982
+ }
983
+
984
+ return NULL;
985
+ }
986
+
987
+ /*
988
+ * PyUpb_CMessage_SetAttr()
989
+ *
990
+ * Implements:
991
+ * msg.foo = foo
992
+ */
993
+ static int PyUpb_CMessage_SetAttr(PyObject* _self, PyObject* attr,
994
+ PyObject* value) {
995
+ PyUpb_CMessage* self = (void*)_self;
996
+ const upb_FieldDef* field;
997
+ if (!PyUpb_CMessage_LookupName(self, attr, &field, NULL,
998
+ PyExc_AttributeError)) {
999
+ return -1;
1000
+ }
1001
+
1002
+ return PyUpb_CMessage_SetFieldValue(_self, field, value,
1003
+ PyExc_AttributeError);
1004
+ }
1005
+
1006
+ static PyObject* PyUpb_CMessage_HasField(PyObject* _self, PyObject* arg) {
1007
+ PyUpb_CMessage* self = (void*)_self;
1008
+ const upb_FieldDef* field;
1009
+ const upb_OneofDef* oneof;
1010
+
1011
+ if (!PyUpb_CMessage_LookupName(self, arg, &field, &oneof, PyExc_ValueError)) {
1012
+ return NULL;
1013
+ }
1014
+
1015
+ if (field && !upb_FieldDef_HasPresence(field)) {
1016
+ PyErr_Format(PyExc_ValueError, "Field %s does not have presence.",
1017
+ upb_FieldDef_FullName(field));
1018
+ return NULL;
1019
+ }
1020
+
1021
+ if (PyUpb_CMessage_IsStub(self)) Py_RETURN_FALSE;
1022
+
1023
+ return PyBool_FromLong(field ? upb_Message_Has(self->ptr.msg, field)
1024
+ : upb_Message_WhichOneof(self->ptr.msg, oneof) !=
1025
+ NULL);
1026
+ }
1027
+
1028
+ static PyObject* PyUpb_CMessage_FindInitializationErrors(PyObject* _self,
1029
+ PyObject* arg);
1030
+
1031
+ static PyObject* PyUpb_CMessage_IsInitializedAppendErrors(PyObject* _self,
1032
+ PyObject* errors) {
1033
+ PyObject* list = PyUpb_CMessage_FindInitializationErrors(_self, NULL);
1034
+ if (!list) return NULL;
1035
+ bool ok = PyList_Size(list) == 0;
1036
+ PyObject* ret = NULL;
1037
+ PyObject* extend_result = NULL;
1038
+ if (!ok) {
1039
+ extend_result = PyObject_CallMethod(errors, "extend", "O", list);
1040
+ if (!extend_result) goto done;
1041
+ }
1042
+ ret = PyBool_FromLong(ok);
1043
+
1044
+ done:
1045
+ Py_XDECREF(list);
1046
+ Py_XDECREF(extend_result);
1047
+ return ret;
1048
+ }
1049
+
1050
+ static PyObject* PyUpb_CMessage_IsInitialized(PyObject* _self, PyObject* args) {
1051
+ PyObject* errors = NULL;
1052
+ if (!PyArg_ParseTuple(args, "|O", &errors)) {
1053
+ return NULL;
1054
+ }
1055
+ if (errors) {
1056
+ // We need to collect a list of unset required fields and append it to
1057
+ // `errors`.
1058
+ return PyUpb_CMessage_IsInitializedAppendErrors(_self, errors);
1059
+ } else {
1060
+ // We just need to return a boolean "true" or "false" for whether all
1061
+ // required fields are set.
1062
+ upb_Message* msg = PyUpb_CMessage_GetIfReified(_self);
1063
+ const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(_self);
1064
+ const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(m));
1065
+ bool initialized = !upb_util_HasUnsetRequired(msg, m, symtab, NULL);
1066
+ return PyBool_FromLong(initialized);
1067
+ }
1068
+ }
1069
+
1070
+ static PyObject* PyUpb_CMessage_ListFieldsItemKey(PyObject* self,
1071
+ PyObject* val) {
1072
+ assert(PyTuple_Check(val));
1073
+ PyObject* field = PyTuple_GetItem(val, 0);
1074
+ const upb_FieldDef* f = PyUpb_FieldDescriptor_GetDef(field);
1075
+ return PyLong_FromLong(upb_FieldDef_Number(f));
1076
+ }
1077
+
1078
+ static bool PyUpb_CMessage_SortFieldList(PyObject* list) {
1079
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1080
+ bool ok = false;
1081
+ PyObject* args = PyTuple_New(0);
1082
+ PyObject* kwargs = PyDict_New();
1083
+ PyObject* method = PyObject_GetAttrString(list, "sort");
1084
+ PyObject* call_result = NULL;
1085
+ if (!args || !kwargs || !method) goto err;
1086
+ if (PyDict_SetItemString(kwargs, "key", state->listfields_item_key) < 0) {
1087
+ goto err;
1088
+ }
1089
+ call_result = PyObject_Call(method, args, kwargs);
1090
+ if (!call_result) goto err;
1091
+ ok = true;
1092
+
1093
+ err:
1094
+ Py_XDECREF(method);
1095
+ Py_XDECREF(args);
1096
+ Py_XDECREF(kwargs);
1097
+ Py_XDECREF(call_result);
1098
+ return ok;
1099
+ }
1100
+
1101
+ static PyObject* PyUpb_CMessage_ListFields(PyObject* _self, PyObject* arg) {
1102
+ PyObject* list = PyList_New(0);
1103
+ upb_Message* msg = PyUpb_CMessage_GetIfReified(_self);
1104
+ if (!msg) return list;
1105
+
1106
+ size_t iter1 = kUpb_Message_Begin;
1107
+ const upb_MessageDef* m = PyUpb_CMessage_GetMsgdef(_self);
1108
+ const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(m));
1109
+ const upb_FieldDef* f;
1110
+ PyObject* field_desc = NULL;
1111
+ PyObject* py_val = NULL;
1112
+ PyObject* tuple = NULL;
1113
+ upb_MessageValue val;
1114
+ uint32_t last_field = 0;
1115
+ bool in_order = true;
1116
+ while (upb_Message_Next(msg, m, symtab, &f, &val, &iter1)) {
1117
+ const uint32_t field_number = upb_FieldDef_Number(f);
1118
+ if (field_number < last_field) in_order = false;
1119
+ last_field = field_number;
1120
+ PyObject* field_desc = PyUpb_FieldDescriptor_Get(f);
1121
+ PyObject* py_val = PyUpb_CMessage_GetFieldValue(_self, f);
1122
+ if (!field_desc || !py_val) goto err;
1123
+ PyObject* tuple = Py_BuildValue("(NN)", field_desc, py_val);
1124
+ field_desc = NULL;
1125
+ py_val = NULL;
1126
+ if (!tuple) goto err;
1127
+ if (PyList_Append(list, tuple)) goto err;
1128
+ Py_DECREF(tuple);
1129
+ tuple = NULL;
1130
+ }
1131
+
1132
+ // Users rely on fields being returned in field number order.
1133
+ if (!in_order && !PyUpb_CMessage_SortFieldList(list)) goto err;
1134
+
1135
+ return list;
1136
+
1137
+ err:
1138
+ Py_XDECREF(field_desc);
1139
+ Py_XDECREF(py_val);
1140
+ Py_XDECREF(tuple);
1141
+ Py_DECREF(list);
1142
+ return NULL;
1143
+ }
1144
+
1145
+ PyObject* PyUpb_CMessage_MergeFrom(PyObject* self, PyObject* arg) {
1146
+ if (self->ob_type != arg->ob_type) {
1147
+ PyErr_Format(PyExc_TypeError,
1148
+ "Parameter to MergeFrom() must be instance of same class: "
1149
+ "expected %S got %S.",
1150
+ Py_TYPE(self), Py_TYPE(arg));
1151
+ return NULL;
1152
+ }
1153
+ // OPT: exit if src is empty.
1154
+ PyObject* subargs = PyTuple_New(0);
1155
+ PyObject* serialized = PyUpb_CMessage_SerializeToString(arg, subargs, NULL);
1156
+ Py_DECREF(subargs);
1157
+ if (!serialized) return NULL;
1158
+ PyObject* ret = PyUpb_CMessage_MergeFromString(self, serialized);
1159
+ Py_DECREF(serialized);
1160
+ Py_DECREF(ret);
1161
+ Py_RETURN_NONE;
1162
+ }
1163
+
1164
+ static PyObject* PyUpb_CMessage_SetInParent(PyObject* _self, PyObject* arg) {
1165
+ PyUpb_CMessage* self = (void*)_self;
1166
+ PyUpb_CMessage_EnsureReified(self);
1167
+ Py_RETURN_NONE;
1168
+ }
1169
+
1170
+ static PyObject* PyUpb_CMessage_UnknownFields(PyObject* _self, PyObject* arg) {
1171
+ // TODO(haberman): re-enable when unknown fields are added.
1172
+ // return PyUpb_UnknownFields_New(_self);
1173
+ PyErr_SetString(PyExc_NotImplementedError, "unknown field accessor");
1174
+ return NULL;
1175
+ }
1176
+
1177
+ PyObject* PyUpb_CMessage_MergeFromString(PyObject* _self, PyObject* arg) {
1178
+ PyUpb_CMessage* self = (void*)_self;
1179
+ char* buf;
1180
+ Py_ssize_t size;
1181
+ PyObject* bytes = NULL;
1182
+
1183
+ if (PyMemoryView_Check(arg)) {
1184
+ bytes = PyBytes_FromObject(arg);
1185
+ // Cannot fail when passed something of the correct type.
1186
+ int err = PyBytes_AsStringAndSize(bytes, &buf, &size);
1187
+ (void)err;
1188
+ assert(err >= 0);
1189
+ } else if (PyBytes_AsStringAndSize(arg, &buf, &size) < 0) {
1190
+ return NULL;
1191
+ }
1192
+
1193
+ PyUpb_CMessage_EnsureReified(self);
1194
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
1195
+ const upb_FileDef* file = upb_MessageDef_File(msgdef);
1196
+ const upb_ExtensionRegistry* extreg =
1197
+ upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
1198
+ const upb_MiniTable* layout = upb_MessageDef_MiniTable(msgdef);
1199
+ upb_Arena* arena = PyUpb_Arena_Get(self->arena);
1200
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1201
+ int options =
1202
+ UPB_DECODE_MAXDEPTH(state->allow_oversize_protos ? UINT32_MAX : 100);
1203
+ upb_DecodeStatus status =
1204
+ upb_Decode(buf, size, self->ptr.msg, layout, extreg, options, arena);
1205
+ Py_XDECREF(bytes);
1206
+ if (status != kUpb_DecodeStatus_Ok) {
1207
+ PyErr_Format(state->decode_error_class, "Error parsing message");
1208
+ return NULL;
1209
+ }
1210
+ PyUpb_CMessage_SyncSubobjs(self);
1211
+ return PyLong_FromSsize_t(size);
1212
+ }
1213
+
1214
+ static PyObject* PyUpb_CMessage_Clear(PyUpb_CMessage* self, PyObject* args);
1215
+
1216
+ static PyObject* PyUpb_CMessage_ParseFromString(PyObject* self, PyObject* arg) {
1217
+ PyObject* tmp = PyUpb_CMessage_Clear((PyUpb_CMessage*)self, NULL);
1218
+ Py_DECREF(tmp);
1219
+ return PyUpb_CMessage_MergeFromString(self, arg);
1220
+ }
1221
+
1222
+ static PyObject* PyUpb_CMessage_ByteSize(PyObject* self, PyObject* args) {
1223
+ // TODO(https://github.com/protocolbuffers/upb/issues/462): At the moment upb
1224
+ // does not have a "byte size" function, so we just serialize to string and
1225
+ // get the size of the string.
1226
+ PyObject* subargs = PyTuple_New(0);
1227
+ PyObject* serialized = PyUpb_CMessage_SerializeToString(self, subargs, NULL);
1228
+ Py_DECREF(subargs);
1229
+ if (!serialized) return NULL;
1230
+ size_t size = PyBytes_Size(serialized);
1231
+ Py_DECREF(serialized);
1232
+ return PyLong_FromSize_t(size);
1233
+ }
1234
+
1235
+ static PyObject* PyUpb_CMessage_Clear(PyUpb_CMessage* self, PyObject* args) {
1236
+ PyUpb_CMessage_EnsureReified(self);
1237
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
1238
+ PyUpb_WeakMap* subobj_map = self->unset_subobj_map;
1239
+
1240
+ if (subobj_map) {
1241
+ upb_Message* msg = PyUpb_CMessage_GetMsg(self);
1242
+ (void)msg; // Suppress unused warning when asserts are disabled.
1243
+ intptr_t iter = PYUPB_WEAKMAP_BEGIN;
1244
+ const void* key;
1245
+ PyObject* obj;
1246
+
1247
+ while (PyUpb_WeakMap_Next(subobj_map, &key, &obj, &iter)) {
1248
+ const upb_FieldDef* f = key;
1249
+ PyUpb_WeakMap_DeleteIter(subobj_map, &iter);
1250
+ if (upb_FieldDef_IsMap(f)) {
1251
+ assert(upb_Message_Get(msg, f).map_val == NULL);
1252
+ PyUpb_MapContainer_Reify(obj, NULL);
1253
+ } else if (upb_FieldDef_IsRepeated(f)) {
1254
+ assert(upb_Message_Get(msg, f).array_val == NULL);
1255
+ PyUpb_RepeatedContainer_Reify(obj, NULL);
1256
+ } else {
1257
+ assert(!upb_Message_Has(msg, f));
1258
+ PyUpb_CMessage* sub = (void*)obj;
1259
+ assert(self == sub->ptr.parent);
1260
+ PyUpb_CMessage_Reify(sub, f, NULL);
1261
+ }
1262
+ }
1263
+ }
1264
+
1265
+ upb_Message_Clear(self->ptr.msg, msgdef);
1266
+ Py_RETURN_NONE;
1267
+ }
1268
+
1269
+ void PyUpb_CMessage_DoClearField(PyObject* _self, const upb_FieldDef* f) {
1270
+ PyUpb_CMessage* self = (void*)_self;
1271
+ PyUpb_CMessage_EnsureReified((PyUpb_CMessage*)self);
1272
+
1273
+ // We must ensure that any stub object is reified so its parent no longer
1274
+ // points to us.
1275
+ PyObject* sub = self->unset_subobj_map
1276
+ ? PyUpb_WeakMap_Get(self->unset_subobj_map, f)
1277
+ : NULL;
1278
+
1279
+ if (upb_FieldDef_IsMap(f)) {
1280
+ // For maps we additionally have to invalidate any iterators. So we need
1281
+ // to get an object even if it's reified.
1282
+ if (!sub) {
1283
+ sub = PyUpb_CMessage_GetFieldValue(_self, f);
1284
+ }
1285
+ PyUpb_MapContainer_EnsureReified(sub);
1286
+ PyUpb_MapContainer_Invalidate(sub);
1287
+ } else if (upb_FieldDef_IsRepeated(f)) {
1288
+ if (sub) {
1289
+ PyUpb_RepeatedContainer_EnsureReified(sub);
1290
+ }
1291
+ } else if (upb_FieldDef_IsSubMessage(f)) {
1292
+ if (sub) {
1293
+ PyUpb_CMessage_EnsureReified((PyUpb_CMessage*)sub);
1294
+ }
1295
+ }
1296
+
1297
+ Py_XDECREF(sub);
1298
+ upb_Message_ClearField(self->ptr.msg, f);
1299
+ }
1300
+
1301
+ static PyObject* PyUpb_CMessage_ClearExtension(PyObject* _self, PyObject* arg) {
1302
+ PyUpb_CMessage* self = (void*)_self;
1303
+ PyUpb_CMessage_EnsureReified(self);
1304
+ const upb_FieldDef* f = PyUpb_CMessage_GetExtensionDef(_self, arg);
1305
+ if (!f) return NULL;
1306
+ PyUpb_CMessage_DoClearField(_self, f);
1307
+ Py_RETURN_NONE;
1308
+ }
1309
+
1310
+ static PyObject* PyUpb_CMessage_ClearField(PyObject* _self, PyObject* arg) {
1311
+ PyUpb_CMessage* self = (void*)_self;
1312
+
1313
+ // We always need EnsureReified() here (even for an unset message) to
1314
+ // preserve behavior like:
1315
+ // msg = FooMessage()
1316
+ // msg.foo.Clear()
1317
+ // assert msg.HasField("foo")
1318
+ PyUpb_CMessage_EnsureReified(self);
1319
+
1320
+ const upb_FieldDef* f;
1321
+ const upb_OneofDef* o;
1322
+ if (!PyUpb_CMessage_LookupName(self, arg, &f, &o, PyExc_ValueError)) {
1323
+ return NULL;
1324
+ }
1325
+
1326
+ if (o) f = upb_Message_WhichOneof(self->ptr.msg, o);
1327
+ PyUpb_CMessage_DoClearField(_self, f);
1328
+ Py_RETURN_NONE;
1329
+ }
1330
+
1331
+ static PyObject* PyUpb_CMessage_DiscardUnknownFields(PyUpb_CMessage* self,
1332
+ PyObject* arg) {
1333
+ PyUpb_CMessage_EnsureReified(self);
1334
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
1335
+ upb_Message_DiscardUnknown(self->ptr.msg, msgdef, 64);
1336
+ Py_RETURN_NONE;
1337
+ }
1338
+
1339
+ static PyObject* PyUpb_CMessage_FindInitializationErrors(PyObject* _self,
1340
+ PyObject* arg) {
1341
+ PyUpb_CMessage* self = (void*)_self;
1342
+ upb_Message* msg = PyUpb_CMessage_GetIfReified(_self);
1343
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
1344
+ const upb_DefPool* ext_pool = upb_FileDef_Pool(upb_MessageDef_File(msgdef));
1345
+ upb_FieldPathEntry* fields;
1346
+ PyObject* ret = PyList_New(0);
1347
+ if (upb_util_HasUnsetRequired(msg, msgdef, ext_pool, &fields)) {
1348
+ char* buf = NULL;
1349
+ size_t size = 0;
1350
+ assert(fields->field);
1351
+ while (fields->field) {
1352
+ upb_FieldPathEntry* field = fields;
1353
+ size_t need = upb_FieldPath_ToText(&fields, buf, size);
1354
+ if (need >= size) {
1355
+ fields = field;
1356
+ size = size ? size * 2 : 16;
1357
+ while (size <= need) size *= 2;
1358
+ buf = realloc(buf, size);
1359
+ need = upb_FieldPath_ToText(&fields, buf, size);
1360
+ assert(size > need);
1361
+ }
1362
+ PyObject* str = PyUnicode_FromString(buf);
1363
+ PyList_Append(ret, str);
1364
+ Py_DECREF(str);
1365
+ }
1366
+ free(buf);
1367
+ }
1368
+ return ret;
1369
+ }
1370
+
1371
+ static PyObject* PyUpb_CMessage_FromString(PyObject* cls,
1372
+ PyObject* serialized) {
1373
+ PyObject* ret = NULL;
1374
+ PyObject* length = NULL;
1375
+
1376
+ ret = PyObject_CallObject(cls, NULL);
1377
+ if (ret == NULL) goto err;
1378
+ length = PyUpb_CMessage_MergeFromString(ret, serialized);
1379
+ if (length == NULL) goto err;
1380
+
1381
+ done:
1382
+ Py_XDECREF(length);
1383
+ return ret;
1384
+
1385
+ err:
1386
+ Py_XDECREF(ret);
1387
+ ret = NULL;
1388
+ goto done;
1389
+ }
1390
+
1391
+ const upb_FieldDef* PyUpb_CMessage_GetExtensionDef(PyObject* _self,
1392
+ PyObject* key) {
1393
+ const upb_FieldDef* f = PyUpb_FieldDescriptor_GetDef(key);
1394
+ if (!f) {
1395
+ PyErr_Clear();
1396
+ PyErr_Format(PyExc_KeyError, "Object %R is not a field descriptor\n", key);
1397
+ return NULL;
1398
+ }
1399
+ if (!upb_FieldDef_IsExtension(f)) {
1400
+ PyErr_Format(PyExc_KeyError, "Field %s is not an extension\n",
1401
+ upb_FieldDef_FullName(f));
1402
+ return NULL;
1403
+ }
1404
+ const upb_MessageDef* msgdef = PyUpb_CMessage_GetMsgdef(_self);
1405
+ if (upb_FieldDef_ContainingType(f) != msgdef) {
1406
+ PyErr_Format(PyExc_KeyError, "Extension doesn't match (%s vs %s)",
1407
+ upb_MessageDef_FullName(msgdef), upb_FieldDef_FullName(f));
1408
+ return NULL;
1409
+ }
1410
+ return f;
1411
+ }
1412
+
1413
+ static PyObject* PyUpb_CMessage_HasExtension(PyObject* _self,
1414
+ PyObject* ext_desc) {
1415
+ upb_Message* msg = PyUpb_CMessage_GetIfReified(_self);
1416
+ const upb_FieldDef* f = PyUpb_CMessage_GetExtensionDef(_self, ext_desc);
1417
+ if (!f) return NULL;
1418
+ if (upb_FieldDef_IsRepeated(f)) {
1419
+ PyErr_SetString(PyExc_KeyError,
1420
+ "Field is repeated. A singular method is required.");
1421
+ return NULL;
1422
+ }
1423
+ if (!msg) Py_RETURN_FALSE;
1424
+ return PyBool_FromLong(upb_Message_Has(msg, f));
1425
+ }
1426
+
1427
+ void PyUpb_CMessage_ReportInitializationErrors(const upb_MessageDef* msgdef,
1428
+ PyObject* errors,
1429
+ PyObject* exc) {
1430
+ PyObject* comma = PyUnicode_FromString(",");
1431
+ PyObject* missing_fields = NULL;
1432
+ if (!comma) goto done;
1433
+ missing_fields = PyUnicode_Join(comma, errors);
1434
+ if (!missing_fields) goto done;
1435
+ PyErr_Format(exc, "Message %s is missing required fields: %U",
1436
+ upb_MessageDef_FullName(msgdef), missing_fields);
1437
+ done:
1438
+ Py_XDECREF(comma);
1439
+ Py_XDECREF(missing_fields);
1440
+ Py_DECREF(errors);
1441
+ }
1442
+
1443
+ PyObject* PyUpb_CMessage_SerializeInternal(PyObject* _self, PyObject* args,
1444
+ PyObject* kwargs,
1445
+ bool check_required) {
1446
+ PyUpb_CMessage* self = (void*)_self;
1447
+ if (!PyUpb_CMessage_Verify((PyObject*)self)) return NULL;
1448
+ static const char* kwlist[] = {"deterministic", NULL};
1449
+ int deterministic = 0;
1450
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p", (char**)(kwlist),
1451
+ &deterministic)) {
1452
+ return NULL;
1453
+ }
1454
+
1455
+ const upb_MessageDef* msgdef = _PyUpb_CMessage_GetMsgdef(self);
1456
+ if (PyUpb_CMessage_IsStub(self)) {
1457
+ // Nothing to serialize, but we do have to check whether the message is
1458
+ // initialized.
1459
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1460
+ PyObject* errors = PyUpb_CMessage_FindInitializationErrors(_self, NULL);
1461
+ if (!errors) return NULL;
1462
+ if (PyList_Size(errors) == 0) {
1463
+ Py_DECREF(errors);
1464
+ return PyBytes_FromStringAndSize(NULL, 0);
1465
+ }
1466
+ PyUpb_CMessage_ReportInitializationErrors(msgdef, errors,
1467
+ state->encode_error_class);
1468
+ return NULL;
1469
+ }
1470
+
1471
+ upb_Arena* arena = upb_Arena_New();
1472
+ const upb_MiniTable* layout = upb_MessageDef_MiniTable(msgdef);
1473
+ size_t size = 0;
1474
+ // Python does not currently have any effective limit on serialization depth.
1475
+ int options = UPB_ENCODE_MAXDEPTH(UINT32_MAX);
1476
+ if (check_required) options |= kUpb_Encode_CheckRequired;
1477
+ if (deterministic) options |= kUpb_Encode_Deterministic;
1478
+ char* pb = upb_Encode(self->ptr.msg, layout, options, arena, &size);
1479
+ PyObject* ret = NULL;
1480
+
1481
+ if (!pb) {
1482
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1483
+ PyObject* errors = PyUpb_CMessage_FindInitializationErrors(_self, NULL);
1484
+ if (PyList_Size(errors) != 0) {
1485
+ PyUpb_CMessage_ReportInitializationErrors(msgdef, errors,
1486
+ state->encode_error_class);
1487
+ } else {
1488
+ PyErr_Format(state->encode_error_class, "Failed to serialize proto");
1489
+ }
1490
+ goto done;
1491
+ }
1492
+
1493
+ ret = PyBytes_FromStringAndSize(pb, size);
1494
+
1495
+ done:
1496
+ upb_Arena_Free(arena);
1497
+ return ret;
1498
+ }
1499
+
1500
+ PyObject* PyUpb_CMessage_SerializeToString(PyObject* _self, PyObject* args,
1501
+ PyObject* kwargs) {
1502
+ return PyUpb_CMessage_SerializeInternal(_self, args, kwargs, true);
1503
+ }
1504
+
1505
+ PyObject* PyUpb_CMessage_SerializePartialToString(PyObject* _self,
1506
+ PyObject* args,
1507
+ PyObject* kwargs) {
1508
+ return PyUpb_CMessage_SerializeInternal(_self, args, kwargs, false);
1509
+ }
1510
+
1511
+ static PyObject* PyUpb_CMessage_WhichOneof(PyObject* _self, PyObject* name) {
1512
+ PyUpb_CMessage* self = (void*)_self;
1513
+ const upb_OneofDef* o;
1514
+ if (!PyUpb_CMessage_LookupName(self, name, NULL, &o, PyExc_ValueError)) {
1515
+ return NULL;
1516
+ }
1517
+ upb_Message* msg = PyUpb_CMessage_GetIfReified(_self);
1518
+ if (!msg) Py_RETURN_NONE;
1519
+ const upb_FieldDef* f = upb_Message_WhichOneof(msg, o);
1520
+ if (!f) Py_RETURN_NONE;
1521
+ return PyUnicode_FromString(upb_FieldDef_Name(f));
1522
+ }
1523
+
1524
+ void PyUpb_CMessage_ClearExtensionDict(PyObject* _self) {
1525
+ PyUpb_CMessage* self = (void*)_self;
1526
+ assert(self->ext_dict);
1527
+ self->ext_dict = NULL;
1528
+ }
1529
+
1530
+ static PyObject* PyUpb_CMessage_GetExtensionDict(PyObject* _self,
1531
+ void* closure) {
1532
+ PyUpb_CMessage* self = (void*)_self;
1533
+ if (self->ext_dict) {
1534
+ Py_INCREF(self->ext_dict);
1535
+ return self->ext_dict;
1536
+ }
1537
+
1538
+ const upb_MessageDef* m = _PyUpb_CMessage_GetMsgdef(self);
1539
+ if (upb_MessageDef_ExtensionRangeCount(m) == 0) {
1540
+ PyErr_SetNone(PyExc_AttributeError);
1541
+ return NULL;
1542
+ }
1543
+
1544
+ self->ext_dict = PyUpb_ExtensionDict_New(_self);
1545
+ return self->ext_dict;
1546
+ }
1547
+
1548
+ static PyGetSetDef PyUpb_CMessage_Getters[] = {
1549
+ {"Extensions", PyUpb_CMessage_GetExtensionDict, NULL, "Extension dict"},
1550
+ {NULL}};
1551
+
1552
+ static PyMethodDef PyUpb_CMessage_Methods[] = {
1553
+ // TODO(https://github.com/protocolbuffers/upb/issues/459)
1554
+ //{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
1555
+ // "Makes a deep copy of the class." },
1556
+ //{ "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS,
1557
+ // "Outputs a unicode representation of the message." },
1558
+ {"ByteSize", (PyCFunction)PyUpb_CMessage_ByteSize, METH_NOARGS,
1559
+ "Returns the size of the message in bytes."},
1560
+ {"Clear", (PyCFunction)PyUpb_CMessage_Clear, METH_NOARGS,
1561
+ "Clears the message."},
1562
+ {"ClearExtension", PyUpb_CMessage_ClearExtension, METH_O,
1563
+ "Clears a message field."},
1564
+ {"ClearField", PyUpb_CMessage_ClearField, METH_O,
1565
+ "Clears a message field."},
1566
+ // TODO(https://github.com/protocolbuffers/upb/issues/459)
1567
+ //{ "CopyFrom", (PyCFunction)CopyFrom, METH_O,
1568
+ // "Copies a protocol message into the current message." },
1569
+ {"DiscardUnknownFields", (PyCFunction)PyUpb_CMessage_DiscardUnknownFields,
1570
+ METH_NOARGS, "Discards the unknown fields."},
1571
+ {"FindInitializationErrors", PyUpb_CMessage_FindInitializationErrors,
1572
+ METH_NOARGS, "Finds unset required fields."},
1573
+ {"FromString", PyUpb_CMessage_FromString, METH_O | METH_CLASS,
1574
+ "Creates new method instance from given serialized data."},
1575
+ {"HasExtension", PyUpb_CMessage_HasExtension, METH_O,
1576
+ "Checks if a message field is set."},
1577
+ {"HasField", PyUpb_CMessage_HasField, METH_O,
1578
+ "Checks if a message field is set."},
1579
+ {"IsInitialized", PyUpb_CMessage_IsInitialized, METH_VARARGS,
1580
+ "Checks if all required fields of a protocol message are set."},
1581
+ {"ListFields", PyUpb_CMessage_ListFields, METH_NOARGS,
1582
+ "Lists all set fields of a message."},
1583
+ {"MergeFrom", PyUpb_CMessage_MergeFrom, METH_O,
1584
+ "Merges a protocol message into the current message."},
1585
+ {"MergeFromString", PyUpb_CMessage_MergeFromString, METH_O,
1586
+ "Merges a serialized message into the current message."},
1587
+ {"ParseFromString", PyUpb_CMessage_ParseFromString, METH_O,
1588
+ "Parses a serialized message into the current message."},
1589
+ // TODO(https://github.com/protocolbuffers/upb/issues/459)
1590
+ //{ "RegisterExtension", (PyCFunction)RegisterExtension, METH_O |
1591
+ // METH_CLASS,
1592
+ // "Registers an extension with the current message." },
1593
+ {"SerializePartialToString",
1594
+ (PyCFunction)PyUpb_CMessage_SerializePartialToString,
1595
+ METH_VARARGS | METH_KEYWORDS,
1596
+ "Serializes the message to a string, even if it isn't initialized."},
1597
+ {"SerializeToString", (PyCFunction)PyUpb_CMessage_SerializeToString,
1598
+ METH_VARARGS | METH_KEYWORDS,
1599
+ "Serializes the message to a string, only for initialized messages."},
1600
+ {"SetInParent", (PyCFunction)PyUpb_CMessage_SetInParent, METH_NOARGS,
1601
+ "Sets the has bit of the given field in its parent message."},
1602
+ {"UnknownFields", (PyCFunction)PyUpb_CMessage_UnknownFields, METH_NOARGS,
1603
+ "Parse unknown field set"},
1604
+ {"WhichOneof", PyUpb_CMessage_WhichOneof, METH_O,
1605
+ "Returns the name of the field set inside a oneof, "
1606
+ "or None if no field is set."},
1607
+ {"_ListFieldsItemKey", PyUpb_CMessage_ListFieldsItemKey,
1608
+ METH_O | METH_STATIC,
1609
+ "Compares ListFields() list entries by field number"},
1610
+ {NULL, NULL}};
1611
+
1612
+ static PyType_Slot PyUpb_CMessage_Slots[] = {
1613
+ {Py_tp_dealloc, PyUpb_CMessage_Dealloc},
1614
+ {Py_tp_doc, "A ProtocolMessage"},
1615
+ {Py_tp_getattro, PyUpb_CMessage_GetAttr},
1616
+ {Py_tp_getset, PyUpb_CMessage_Getters},
1617
+ {Py_tp_hash, PyObject_HashNotImplemented},
1618
+ {Py_tp_methods, PyUpb_CMessage_Methods},
1619
+ {Py_tp_new, PyUpb_CMessage_New},
1620
+ {Py_tp_str, PyUpb_CMessage_ToString},
1621
+ {Py_tp_repr, PyUpb_CMessage_ToString},
1622
+ {Py_tp_richcompare, PyUpb_CMessage_RichCompare},
1623
+ {Py_tp_setattro, PyUpb_CMessage_SetAttr},
1624
+ {Py_tp_init, PyUpb_CMessage_Init},
1625
+ {0, NULL}};
1626
+
1627
+ PyType_Spec PyUpb_CMessage_Spec = {
1628
+ PYUPB_MODULE_NAME ".CMessage", // tp_name
1629
+ sizeof(PyUpb_CMessage), // tp_basicsize
1630
+ 0, // tp_itemsize
1631
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
1632
+ PyUpb_CMessage_Slots,
1633
+ };
1634
+
1635
+ // -----------------------------------------------------------------------------
1636
+ // MessageMeta
1637
+ // -----------------------------------------------------------------------------
1638
+
1639
+ // MessageMeta is the metaclass for message objects. The generated code uses it
1640
+ // to construct message classes, ie.
1641
+ //
1642
+ // FooMessage = _message.MessageMeta('FooMessage', (_message.Message), {...})
1643
+ //
1644
+ // (This is not quite true: at the moment the Python library subclasses
1645
+ // MessageMeta, and uses that subclass as the metaclass. There is a TODO below
1646
+ // to simplify this, so that the illustration above is indeed accurate).
1647
+
1648
+ typedef struct {
1649
+ const upb_MiniTable* layout;
1650
+ PyObject* py_message_descriptor;
1651
+ } PyUpb_MessageMeta;
1652
+
1653
+ // The PyUpb_MessageMeta struct is trailing data tacked onto the end of
1654
+ // MessageMeta instances. This means that we get our instances of this struct
1655
+ // by adding the appropriate number of bytes.
1656
+ static PyUpb_MessageMeta* PyUpb_GetMessageMeta(PyObject* cls) {
1657
+ #ifndef NDEBUG
1658
+ PyUpb_ModuleState* state = PyUpb_ModuleState_MaybeGet();
1659
+ assert(!state || cls->ob_type == state->message_meta_type);
1660
+ #endif
1661
+ return (PyUpb_MessageMeta*)((char*)cls + cpython_bits.type_basicsize);
1662
+ }
1663
+
1664
+ static const upb_MessageDef* PyUpb_MessageMeta_GetMsgdef(PyObject* cls) {
1665
+ PyUpb_MessageMeta* self = PyUpb_GetMessageMeta(cls);
1666
+ return PyUpb_Descriptor_GetDef(self->py_message_descriptor);
1667
+ }
1668
+
1669
+ PyObject* PyUpb_MessageMeta_DoCreateClass(PyObject* py_descriptor,
1670
+ const char* name, PyObject* dict) {
1671
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1672
+ PyTypeObject* descriptor_type = state->descriptor_types[kPyUpb_Descriptor];
1673
+ if (!PyObject_TypeCheck(py_descriptor, descriptor_type)) {
1674
+ return PyErr_Format(PyExc_TypeError, "Expected a message Descriptor");
1675
+ }
1676
+
1677
+ const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(py_descriptor);
1678
+ assert(msgdef);
1679
+ assert(!PyUpb_ObjCache_Get(upb_MessageDef_MiniTable(msgdef)));
1680
+
1681
+ PyObject* slots = PyTuple_New(0);
1682
+ if (!slots) return NULL;
1683
+ int status = PyDict_SetItemString(dict, "__slots__", slots);
1684
+ Py_DECREF(slots);
1685
+ if (status < 0) return NULL;
1686
+
1687
+ // Bases are either:
1688
+ // (CMessage, Message) # for regular messages
1689
+ // (CMessage, Message, WktBase) # For well-known types
1690
+ PyObject* wkt_bases = PyUpb_GetWktBases(state);
1691
+ PyObject* wkt_base =
1692
+ PyDict_GetItemString(wkt_bases, upb_MessageDef_FullName(msgdef));
1693
+ PyObject* args;
1694
+ if (wkt_base == NULL) {
1695
+ args = Py_BuildValue("s(OO)O", name, state->cmessage_type,
1696
+ state->message_class, dict);
1697
+ } else {
1698
+ args = Py_BuildValue("s(OOO)O", name, state->cmessage_type,
1699
+ state->message_class, wkt_base, dict);
1700
+ }
1701
+
1702
+ PyObject* ret = cpython_bits.type_new(state->message_meta_type, args, NULL);
1703
+ Py_DECREF(args);
1704
+ if (!ret) return NULL;
1705
+
1706
+ PyUpb_MessageMeta* meta = PyUpb_GetMessageMeta(ret);
1707
+ meta->py_message_descriptor = py_descriptor;
1708
+ meta->layout = upb_MessageDef_MiniTable(msgdef);
1709
+ Py_INCREF(meta->py_message_descriptor);
1710
+
1711
+ PyUpb_ObjCache_Add(meta->layout, ret);
1712
+
1713
+ return ret;
1714
+ }
1715
+
1716
+ static PyObject* PyUpb_MessageMeta_New(PyTypeObject* type, PyObject* args,
1717
+ PyObject* kwargs) {
1718
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1719
+ static const char* kwlist[] = {"name", "bases", "dict", 0};
1720
+ PyObject *bases, *dict;
1721
+ const char* name;
1722
+
1723
+ // Check arguments: (name, bases, dict)
1724
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", (char**)kwlist,
1725
+ &name, &PyTuple_Type, &bases, &PyDict_Type,
1726
+ &dict)) {
1727
+ return NULL;
1728
+ }
1729
+
1730
+ // Check bases: only (), or (message.Message,) are allowed
1731
+ Py_ssize_t size = PyTuple_Size(bases);
1732
+ if (!(size == 0 ||
1733
+ (size == 1 && PyTuple_GetItem(bases, 0) == state->message_class))) {
1734
+ PyErr_Format(PyExc_TypeError,
1735
+ "A Message class can only inherit from Message, not %S",
1736
+ bases);
1737
+ return NULL;
1738
+ }
1739
+
1740
+ // Check dict['DESCRIPTOR']
1741
+ PyObject* py_descriptor = PyDict_GetItemString(dict, "DESCRIPTOR");
1742
+ if (py_descriptor == NULL) {
1743
+ PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
1744
+ return NULL;
1745
+ }
1746
+
1747
+ const upb_MessageDef* m = PyUpb_Descriptor_GetDef(py_descriptor);
1748
+ PyObject* ret = PyUpb_ObjCache_Get(upb_MessageDef_MiniTable(m));
1749
+ if (ret) return ret;
1750
+ return PyUpb_MessageMeta_DoCreateClass(py_descriptor, name, dict);
1751
+ }
1752
+
1753
+ static void PyUpb_MessageMeta_Dealloc(PyObject* self) {
1754
+ PyUpb_MessageMeta* meta = PyUpb_GetMessageMeta(self);
1755
+ PyUpb_ObjCache_Delete(meta->layout);
1756
+ Py_DECREF(meta->py_message_descriptor);
1757
+ PyTypeObject* tp = Py_TYPE(self);
1758
+ cpython_bits.type_dealloc(self);
1759
+ Py_DECREF(tp);
1760
+ }
1761
+
1762
+ void PyUpb_MessageMeta_AddFieldNumber(PyObject* self, const upb_FieldDef* f) {
1763
+ PyObject* name =
1764
+ PyUnicode_FromFormat("%s_FIELD_NUMBER", upb_FieldDef_Name(f));
1765
+ PyObject* upper = PyObject_CallMethod(name, "upper", "");
1766
+ PyObject_SetAttr(self, upper, PyLong_FromLong(upb_FieldDef_Number(f)));
1767
+ Py_DECREF(name);
1768
+ Py_DECREF(upper);
1769
+ }
1770
+
1771
+ static PyObject* PyUpb_MessageMeta_GetDynamicAttr(PyObject* self,
1772
+ PyObject* name) {
1773
+ const char* name_buf = PyUpb_GetStrData(name);
1774
+ if (!name_buf) return NULL;
1775
+ const upb_MessageDef* msgdef = PyUpb_MessageMeta_GetMsgdef(self);
1776
+ const upb_FileDef* filedef = upb_MessageDef_File(msgdef);
1777
+ const upb_DefPool* symtab = upb_FileDef_Pool(filedef);
1778
+
1779
+ PyObject* py_key =
1780
+ PyBytes_FromFormat("%s.%s", upb_MessageDef_FullName(msgdef), name_buf);
1781
+ const char* key = PyUpb_GetStrData(py_key);
1782
+ PyObject* ret = NULL;
1783
+ const upb_MessageDef* nested = upb_DefPool_FindMessageByName(symtab, key);
1784
+ const upb_EnumDef* enumdef;
1785
+ const upb_EnumValueDef* enumval;
1786
+ const upb_FieldDef* ext;
1787
+
1788
+ if (nested) {
1789
+ ret = PyUpb_Descriptor_GetClass(nested);
1790
+ } else if ((enumdef = upb_DefPool_FindEnumByName(symtab, key))) {
1791
+ PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
1792
+ PyObject* klass = state->enum_type_wrapper_class;
1793
+ ret = PyUpb_EnumDescriptor_Get(enumdef);
1794
+ ret = PyObject_CallFunctionObjArgs(klass, ret, NULL);
1795
+ } else if ((enumval = upb_DefPool_FindEnumByNameval(symtab, key))) {
1796
+ ret = PyLong_FromLong(upb_EnumValueDef_Number(enumval));
1797
+ } else if ((ext = upb_DefPool_FindExtensionByName(symtab, key))) {
1798
+ ret = PyUpb_FieldDescriptor_Get(ext);
1799
+ }
1800
+
1801
+ Py_DECREF(py_key);
1802
+
1803
+ const char* suffix = "_FIELD_NUMBER";
1804
+ size_t n = strlen(name_buf);
1805
+ size_t suffix_n = strlen(suffix);
1806
+ if (n > suffix_n && memcmp(suffix, name_buf + n - suffix_n, suffix_n) == 0) {
1807
+ // We can't look up field names dynamically, because the <NAME>_FIELD_NUMBER
1808
+ // naming scheme upper-cases the field name and is therefore non-reversible.
1809
+ // So we just add all field numbers.
1810
+ int n = upb_MessageDef_FieldCount(msgdef);
1811
+ for (int i = 0; i < n; i++) {
1812
+ PyUpb_MessageMeta_AddFieldNumber(self, upb_MessageDef_Field(msgdef, i));
1813
+ }
1814
+ n = upb_MessageDef_NestedExtensionCount(msgdef);
1815
+ for (int i = 0; i < n; i++) {
1816
+ PyUpb_MessageMeta_AddFieldNumber(
1817
+ self, upb_MessageDef_NestedExtension(msgdef, i));
1818
+ }
1819
+ ret = PyObject_GenericGetAttr(self, name);
1820
+ }
1821
+
1822
+ return ret;
1823
+ }
1824
+
1825
+ static PyObject* PyUpb_MessageMeta_GetAttr(PyObject* self, PyObject* name) {
1826
+ // We want to first delegate to the type's tp_dict to retrieve any attributes
1827
+ // that were previously calculated and cached in the type's dict.
1828
+ PyObject* ret = cpython_bits.type_getattro(self, name);
1829
+ if (ret) return ret;
1830
+
1831
+ // We did not find a cached attribute. Try to calculate the attribute
1832
+ // dynamically, using the descriptor as an argument.
1833
+ PyErr_Clear();
1834
+ ret = PyUpb_MessageMeta_GetDynamicAttr(self, name);
1835
+
1836
+ if (ret) {
1837
+ PyObject_SetAttr(self, name, ret);
1838
+ PyErr_Clear();
1839
+ return ret;
1840
+ }
1841
+
1842
+ PyErr_SetObject(PyExc_AttributeError, name);
1843
+ return NULL;
1844
+ }
1845
+
1846
+ static PyType_Slot PyUpb_MessageMeta_Slots[] = {
1847
+ {Py_tp_new, PyUpb_MessageMeta_New},
1848
+ {Py_tp_dealloc, PyUpb_MessageMeta_Dealloc},
1849
+ {Py_tp_getattro, PyUpb_MessageMeta_GetAttr},
1850
+ {0, NULL}};
1851
+
1852
+ static PyType_Spec PyUpb_MessageMeta_Spec = {
1853
+ PYUPB_MODULE_NAME ".MessageMeta", // tp_name
1854
+ 0, // To be filled in by size of base // tp_basicsize
1855
+ 0, // tp_itemsize
1856
+ // TODO(haberman): remove BASETYPE, Python should just use MessageMeta
1857
+ // directly instead of subclassing it.
1858
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
1859
+ PyUpb_MessageMeta_Slots,
1860
+ };
1861
+
1862
+ static PyObject* PyUpb_MessageMeta_CreateType(void) {
1863
+ PyObject* bases = Py_BuildValue("(O)", &PyType_Type);
1864
+ if (!bases) return NULL;
1865
+ PyUpb_MessageMeta_Spec.basicsize =
1866
+ cpython_bits.type_basicsize + sizeof(PyUpb_MessageMeta);
1867
+ PyObject* type = PyType_FromSpecWithBases(&PyUpb_MessageMeta_Spec, bases);
1868
+ Py_DECREF(bases);
1869
+ return type;
1870
+ }
1871
+
1872
+ bool PyUpb_InitMessage(PyObject* m) {
1873
+ if (!PyUpb_CPythonBits_Init(&cpython_bits)) return false;
1874
+ PyObject* message_meta_type = PyUpb_MessageMeta_CreateType();
1875
+
1876
+ PyUpb_ModuleState* state = PyUpb_ModuleState_GetFromModule(m);
1877
+ state->cmessage_type = PyUpb_AddClass(m, &PyUpb_CMessage_Spec);
1878
+ state->message_meta_type = (PyTypeObject*)message_meta_type;
1879
+
1880
+ if (!state->cmessage_type || !state->message_meta_type) return false;
1881
+ if (PyModule_AddObject(m, "MessageMeta", message_meta_type)) return false;
1882
+ state->listfields_item_key = PyObject_GetAttrString(
1883
+ (PyObject*)state->cmessage_type, "_ListFieldsItemKey");
1884
+
1885
+ PyObject* mod =
1886
+ PyImport_ImportModule(PYUPB_PROTOBUF_PUBLIC_PACKAGE ".message");
1887
+ if (mod == NULL) return false;
1888
+
1889
+ state->encode_error_class = PyObject_GetAttrString(mod, "EncodeError");
1890
+ state->decode_error_class = PyObject_GetAttrString(mod, "DecodeError");
1891
+ state->message_class = PyObject_GetAttrString(mod, "Message");
1892
+ Py_DECREF(mod);
1893
+
1894
+ PyObject* enum_type_wrapper = PyImport_ImportModule(
1895
+ PYUPB_PROTOBUF_INTERNAL_PACKAGE ".enum_type_wrapper");
1896
+ if (enum_type_wrapper == NULL) return false;
1897
+
1898
+ state->enum_type_wrapper_class =
1899
+ PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper");
1900
+ Py_DECREF(enum_type_wrapper);
1901
+
1902
+ if (!state->encode_error_class || !state->decode_error_class ||
1903
+ !state->message_class || !state->listfields_item_key ||
1904
+ !state->enum_type_wrapper_class) {
1905
+ return false;
1906
+ }
1907
+
1908
+ return true;
1909
+ }