ruby_memprofiler_pprof 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }