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,1118 @@
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
+ /*
29
+ * lupb_Message -- Message/Array/Map objects in Lua/C that wrap upb/msg.h
30
+ */
31
+
32
+ #include "upb/msg.h"
33
+
34
+ #include <float.h>
35
+ #include <math.h>
36
+ #include <stddef.h>
37
+ #include <stdlib.h>
38
+ #include <string.h>
39
+
40
+ #include "lauxlib.h"
41
+ #include "upb/bindings/lua/upb.h"
42
+ #include "upb/json_decode.h"
43
+ #include "upb/json_encode.h"
44
+ #include "upb/port_def.inc"
45
+ #include "upb/reflection.h"
46
+ #include "upb/text_encode.h"
47
+
48
+ /*
49
+ * Message/Map/Array objects. These objects form a directed graph: a message
50
+ * can contain submessages, arrays, and maps, which can then point to other
51
+ * messages. This graph can technically be cyclic, though this is an error and
52
+ * a cyclic graph cannot be serialized. So it's better to think of this as a
53
+ * tree of objects.
54
+ *
55
+ * The actual data exists at the upb level (upb_Message, upb_Map, upb_Array),
56
+ * independently of Lua. The upb objects contain all the canonical data and
57
+ * edges between objects. Lua wrapper objects expose the upb objects to Lua,
58
+ * but ultimately they are just wrappers. They pass through all reads and
59
+ * writes to the underlying upb objects.
60
+ *
61
+ * Each upb object lives in a upb arena. We have a Lua object to wrap the upb
62
+ * arena, but arenas are never exposed to the user. The Lua arena object just
63
+ * serves to own the upb arena and free it at the proper time, once the Lua GC
64
+ * has determined that there are no more references to anything that lives in
65
+ * that arena. All wrapper objects strongly reference the arena to which they
66
+ * belong.
67
+ *
68
+ * A global object cache stores a mapping of C pointer (upb_Message*,
69
+ * upb_Array*, upb_Map*) to a corresponding Lua wrapper. These references are
70
+ * weak so that the wrappers can be collected if they are no longer needed. A
71
+ * new wrapper object can always be recreated later.
72
+ *
73
+ * +-----+
74
+ * lupb_Arena |cache|-weak-+
75
+ * | ^ +-----+ |
76
+ * | | V
77
+ * Lua level | +------------lupb_Message
78
+ * ----------------|-----------------|------------------------------------------
79
+ * upb level | |
80
+ * | +----V----------------------------------+
81
+ * +->upb_Arena | upb_Message ...(empty arena storage) |
82
+ * +---------------------------------------+
83
+ *
84
+ * If the user creates a reference between two objects that have different
85
+ * arenas, we need to fuse the two arenas together, so that the blocks will
86
+ * outlive both arenas.
87
+ *
88
+ * +-------------------------->(fused)<----------------+
89
+ * | |
90
+ * V +-----+ V
91
+ * lupb_Arena +-weak-|cache|-weak-+ lupb_Arena
92
+ * | ^ | +-----+ | ^ |
93
+ * | | V V | |
94
+ * Lua level | +------------lupb_Message lupb_Message--+ |
95
+ * ----------------|-----------------|----------------------|-----------|------
96
+ * upb level | | | |
97
+ * | +----V--------+ +----V--------+ V
98
+ * +->upb_Arena | upb_Message | | upb_Message | upb_Arena
99
+ * +------|------+ +--^----------+
100
+ * +------------------+
101
+ * Key invariants:
102
+ * 1. every wrapper references the arena that contains it.
103
+ * 2. every fused arena includes all arenas that own upb objects reachable
104
+ * from that arena. In other words, when a wrapper references an arena,
105
+ * this is sufficient to ensure that any upb object reachable from that
106
+ * wrapper will stay alive.
107
+ *
108
+ * Additionally, every message object contains a strong reference to the
109
+ * corresponding Descriptor object. Likewise, array/map objects reference a
110
+ * Descriptor object if they are typed to store message values.
111
+ */
112
+
113
+ #define LUPB_ARENA "lupb.arena"
114
+ #define LUPB_ARRAY "lupb.array"
115
+ #define LUPB_MAP "lupb.map"
116
+ #define LUPB_MSG "lupb.msg"
117
+
118
+ #define LUPB_ARENA_INDEX 1
119
+ #define LUPB_MSGDEF_INDEX 2 /* For msg, and map/array that store msg */
120
+
121
+ static void lupb_Message_Newmsgwrapper(lua_State* L, int narg,
122
+ upb_MessageValue val);
123
+ static upb_Message* lupb_msg_check(lua_State* L, int narg);
124
+
125
+ static upb_CType lupb_checkfieldtype(lua_State* L, int narg) {
126
+ uint32_t n = lupb_checkuint32(L, narg);
127
+ bool ok = n >= kUpb_CType_Bool && n <= kUpb_CType_Bytes;
128
+ luaL_argcheck(L, ok, narg, "invalid field type");
129
+ return n;
130
+ }
131
+
132
+ char cache_key;
133
+
134
+ /* lupb_cacheinit()
135
+ *
136
+ * Creates the global cache used by lupb_cacheget() and lupb_cacheset().
137
+ */
138
+ static void lupb_cacheinit(lua_State* L) {
139
+ /* Create our object cache. */
140
+ lua_newtable(L);
141
+
142
+ /* Cache metatable gives the cache weak values */
143
+ lua_createtable(L, 0, 1);
144
+ lua_pushstring(L, "v");
145
+ lua_setfield(L, -2, "__mode");
146
+ lua_setmetatable(L, -2);
147
+
148
+ /* Set cache in the registry. */
149
+ lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key);
150
+ }
151
+
152
+ /* lupb_cacheget()
153
+ *
154
+ * Pushes cache[key] and returns true if this key is present in the cache.
155
+ * Otherwise returns false and leaves nothing on the stack.
156
+ */
157
+ static bool lupb_cacheget(lua_State* L, const void* key) {
158
+ if (key == NULL) {
159
+ lua_pushnil(L);
160
+ return true;
161
+ }
162
+
163
+ lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
164
+ lua_rawgetp(L, -1, key);
165
+ if (lua_isnil(L, -1)) {
166
+ lua_pop(L, 2); /* Pop table, nil. */
167
+ return false;
168
+ } else {
169
+ lua_replace(L, -2); /* Replace cache table. */
170
+ return true;
171
+ }
172
+ }
173
+
174
+ /* lupb_cacheset()
175
+ *
176
+ * Sets cache[key] = val, where "val" is the value at the top of the stack.
177
+ * Does not pop the value.
178
+ */
179
+ static void lupb_cacheset(lua_State* L, const void* key) {
180
+ lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
181
+ lua_pushvalue(L, -2);
182
+ lua_rawsetp(L, -2, key);
183
+ lua_pop(L, 1); /* Pop table. */
184
+ }
185
+
186
+ /* lupb_Arena *****************************************************************/
187
+
188
+ /* lupb_Arena only exists to wrap a upb_Arena. It is never exposed to users; it
189
+ * is an internal memory management detail. Other wrapper objects refer to this
190
+ * object from their userdata to keep the arena-owned data alive.
191
+ */
192
+
193
+ typedef struct {
194
+ upb_Arena* arena;
195
+ } lupb_Arena;
196
+
197
+ static upb_Arena* lupb_Arena_check(lua_State* L, int narg) {
198
+ lupb_Arena* a = luaL_checkudata(L, narg, LUPB_ARENA);
199
+ return a->arena;
200
+ }
201
+
202
+ upb_Arena* lupb_Arena_pushnew(lua_State* L) {
203
+ lupb_Arena* a = lupb_newuserdata(L, sizeof(lupb_Arena), 1, LUPB_ARENA);
204
+ a->arena = upb_Arena_New();
205
+ return a->arena;
206
+ }
207
+
208
+ /**
209
+ * lupb_Arena_Fuse()
210
+ *
211
+ * Merges |from| into |to| so that there is a single arena group that contains
212
+ * both, and both arenas will point at this new table. */
213
+ static void lupb_Arena_Fuse(lua_State* L, int to, int from) {
214
+ upb_Arena* to_arena = lupb_Arena_check(L, to);
215
+ upb_Arena* from_arena = lupb_Arena_check(L, from);
216
+ upb_Arena_Fuse(to_arena, from_arena);
217
+ }
218
+
219
+ static void lupb_Arena_Fuseobjs(lua_State* L, int to, int from) {
220
+ lua_getiuservalue(L, to, LUPB_ARENA_INDEX);
221
+ lua_getiuservalue(L, from, LUPB_ARENA_INDEX);
222
+ lupb_Arena_Fuse(L, lua_absindex(L, -2), lua_absindex(L, -1));
223
+ lua_pop(L, 2);
224
+ }
225
+
226
+ static int lupb_Arena_gc(lua_State* L) {
227
+ upb_Arena* a = lupb_Arena_check(L, 1);
228
+ upb_Arena_Free(a);
229
+ return 0;
230
+ }
231
+
232
+ static const struct luaL_Reg lupb_Arena_mm[] = {{"__gc", lupb_Arena_gc},
233
+ {NULL, NULL}};
234
+
235
+ /* lupb_Arenaget()
236
+ *
237
+ * Returns the arena from the given message, array, or map object.
238
+ */
239
+ static upb_Arena* lupb_Arenaget(lua_State* L, int narg) {
240
+ upb_Arena* arena;
241
+ lua_getiuservalue(L, narg, LUPB_ARENA_INDEX);
242
+ arena = lupb_Arena_check(L, -1);
243
+ lua_pop(L, 1);
244
+ return arena;
245
+ }
246
+
247
+ /* upb <-> Lua type conversion ************************************************/
248
+
249
+ /* Whether string data should be copied into the containing arena. We can
250
+ * avoid a copy if the string data is only needed temporarily (like for a map
251
+ * lookup).
252
+ */
253
+ typedef enum {
254
+ LUPB_COPY, /* Copy string data into the arena. */
255
+ LUPB_REF /* Reference the Lua copy of the string data. */
256
+ } lupb_copy_t;
257
+
258
+ /**
259
+ * lupb_tomsgval()
260
+ *
261
+ * Converts the given Lua value |narg| to a upb_MessageValue.
262
+ */
263
+ static upb_MessageValue lupb_tomsgval(lua_State* L, upb_CType type, int narg,
264
+ int container, lupb_copy_t copy) {
265
+ upb_MessageValue ret;
266
+ switch (type) {
267
+ case kUpb_CType_Int32:
268
+ case kUpb_CType_Enum:
269
+ ret.int32_val = lupb_checkint32(L, narg);
270
+ break;
271
+ case kUpb_CType_Int64:
272
+ ret.int64_val = lupb_checkint64(L, narg);
273
+ break;
274
+ case kUpb_CType_UInt32:
275
+ ret.uint32_val = lupb_checkuint32(L, narg);
276
+ break;
277
+ case kUpb_CType_UInt64:
278
+ ret.uint64_val = lupb_checkuint64(L, narg);
279
+ break;
280
+ case kUpb_CType_Double:
281
+ ret.double_val = lupb_checkdouble(L, narg);
282
+ break;
283
+ case kUpb_CType_Float:
284
+ ret.float_val = lupb_checkfloat(L, narg);
285
+ break;
286
+ case kUpb_CType_Bool:
287
+ ret.bool_val = lupb_checkbool(L, narg);
288
+ break;
289
+ case kUpb_CType_String:
290
+ case kUpb_CType_Bytes: {
291
+ size_t len;
292
+ const char* ptr = lupb_checkstring(L, narg, &len);
293
+ switch (copy) {
294
+ case LUPB_COPY: {
295
+ upb_Arena* arena = lupb_Arenaget(L, container);
296
+ char* data = upb_Arena_Malloc(arena, len);
297
+ memcpy(data, ptr, len);
298
+ ret.str_val = upb_StringView_FromDataAndSize(data, len);
299
+ break;
300
+ }
301
+ case LUPB_REF:
302
+ ret.str_val = upb_StringView_FromDataAndSize(ptr, len);
303
+ break;
304
+ }
305
+ break;
306
+ }
307
+ case kUpb_CType_Message:
308
+ ret.msg_val = lupb_msg_check(L, narg);
309
+ /* Typecheck message. */
310
+ lua_getiuservalue(L, container, LUPB_MSGDEF_INDEX);
311
+ lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX);
312
+ luaL_argcheck(L, lua_rawequal(L, -1, -2), narg, "message type mismatch");
313
+ lua_pop(L, 2);
314
+ break;
315
+ }
316
+ return ret;
317
+ }
318
+
319
+ void lupb_pushmsgval(lua_State* L, int container, upb_CType type,
320
+ upb_MessageValue val) {
321
+ switch (type) {
322
+ case kUpb_CType_Int32:
323
+ case kUpb_CType_Enum:
324
+ lupb_pushint32(L, val.int32_val);
325
+ return;
326
+ case kUpb_CType_Int64:
327
+ lupb_pushint64(L, val.int64_val);
328
+ return;
329
+ case kUpb_CType_UInt32:
330
+ lupb_pushuint32(L, val.uint32_val);
331
+ return;
332
+ case kUpb_CType_UInt64:
333
+ lupb_pushuint64(L, val.uint64_val);
334
+ return;
335
+ case kUpb_CType_Double:
336
+ lua_pushnumber(L, val.double_val);
337
+ return;
338
+ case kUpb_CType_Float:
339
+ lua_pushnumber(L, val.float_val);
340
+ return;
341
+ case kUpb_CType_Bool:
342
+ lua_pushboolean(L, val.bool_val);
343
+ return;
344
+ case kUpb_CType_String:
345
+ case kUpb_CType_Bytes:
346
+ lua_pushlstring(L, val.str_val.data, val.str_val.size);
347
+ return;
348
+ case kUpb_CType_Message:
349
+ assert(container);
350
+ if (!lupb_cacheget(L, val.msg_val)) {
351
+ lupb_Message_Newmsgwrapper(L, container, val);
352
+ }
353
+ return;
354
+ }
355
+ LUPB_UNREACHABLE();
356
+ }
357
+
358
+ /* lupb_array *****************************************************************/
359
+
360
+ typedef struct {
361
+ upb_Array* arr;
362
+ upb_CType type;
363
+ } lupb_array;
364
+
365
+ static lupb_array* lupb_array_check(lua_State* L, int narg) {
366
+ return luaL_checkudata(L, narg, LUPB_ARRAY);
367
+ }
368
+
369
+ /**
370
+ * lupb_array_checkindex()
371
+ *
372
+ * Checks the array index at Lua stack index |narg| to verify that it is an
373
+ * integer between 1 and |max|, inclusively. Also corrects it to be zero-based
374
+ * for C.
375
+ */
376
+ static int lupb_array_checkindex(lua_State* L, int narg, uint32_t max) {
377
+ uint32_t n = lupb_checkuint32(L, narg);
378
+ luaL_argcheck(L, n != 0 && n <= max, narg, "invalid array index");
379
+ return n - 1; /* Lua uses 1-based indexing. */
380
+ }
381
+
382
+ /* lupb_array Public API */
383
+
384
+ /* lupb_Array_New():
385
+ *
386
+ * Handles:
387
+ * Array(upb.TYPE_INT32)
388
+ * Array(message_type)
389
+ */
390
+ static int lupb_Array_New(lua_State* L) {
391
+ int arg_count = lua_gettop(L);
392
+ lupb_array* larray;
393
+ upb_Arena* arena;
394
+
395
+ if (lua_type(L, 1) == LUA_TNUMBER) {
396
+ upb_CType type = lupb_checkfieldtype(L, 1);
397
+ larray = lupb_newuserdata(L, sizeof(*larray), 1, LUPB_ARRAY);
398
+ larray->type = type;
399
+ } else {
400
+ lupb_MessageDef_check(L, 1);
401
+ larray = lupb_newuserdata(L, sizeof(*larray), 2, LUPB_ARRAY);
402
+ larray->type = kUpb_CType_Message;
403
+ lua_pushvalue(L, 1);
404
+ lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX);
405
+ }
406
+
407
+ arena = lupb_Arena_pushnew(L);
408
+ lua_setiuservalue(L, -2, LUPB_ARENA_INDEX);
409
+
410
+ larray->arr = upb_Array_New(arena, larray->type);
411
+ lupb_cacheset(L, larray->arr);
412
+
413
+ if (arg_count > 1) {
414
+ /* Set initial fields from table. */
415
+ int msg = arg_count + 1;
416
+ lua_pushnil(L);
417
+ while (lua_next(L, 2) != 0) {
418
+ lua_pushvalue(L, -2); /* now stack is key, val, key */
419
+ lua_insert(L, -3); /* now stack is key, key, val */
420
+ lua_settable(L, msg);
421
+ }
422
+ }
423
+
424
+ return 1;
425
+ }
426
+
427
+ /* lupb_Array_Newindex():
428
+ *
429
+ * Handles:
430
+ * array[idx] = val
431
+ *
432
+ * idx can be within the array or one past the end to extend.
433
+ */
434
+ static int lupb_Array_Newindex(lua_State* L) {
435
+ lupb_array* larray = lupb_array_check(L, 1);
436
+ size_t size = upb_Array_Size(larray->arr);
437
+ uint32_t n = lupb_array_checkindex(L, 2, size + 1);
438
+ upb_MessageValue msgval = lupb_tomsgval(L, larray->type, 3, 1, LUPB_COPY);
439
+
440
+ if (n == size) {
441
+ upb_Array_Append(larray->arr, msgval, lupb_Arenaget(L, 1));
442
+ } else {
443
+ upb_Array_Set(larray->arr, n, msgval);
444
+ }
445
+
446
+ if (larray->type == kUpb_CType_Message) {
447
+ lupb_Arena_Fuseobjs(L, 1, 3);
448
+ }
449
+
450
+ return 0; /* 1 for chained assignments? */
451
+ }
452
+
453
+ /* lupb_array_index():
454
+ *
455
+ * Handles:
456
+ * array[idx] -> val
457
+ *
458
+ * idx must be within the array.
459
+ */
460
+ static int lupb_array_index(lua_State* L) {
461
+ lupb_array* larray = lupb_array_check(L, 1);
462
+ size_t size = upb_Array_Size(larray->arr);
463
+ uint32_t n = lupb_array_checkindex(L, 2, size);
464
+ upb_MessageValue val = upb_Array_Get(larray->arr, n);
465
+
466
+ lupb_pushmsgval(L, 1, larray->type, val);
467
+
468
+ return 1;
469
+ }
470
+
471
+ /* lupb_array_len():
472
+ *
473
+ * Handles:
474
+ * #array -> len
475
+ */
476
+ static int lupb_array_len(lua_State* L) {
477
+ lupb_array* larray = lupb_array_check(L, 1);
478
+ lua_pushnumber(L, upb_Array_Size(larray->arr));
479
+ return 1;
480
+ }
481
+
482
+ static const struct luaL_Reg lupb_array_mm[] = {
483
+ {"__index", lupb_array_index},
484
+ {"__len", lupb_array_len},
485
+ {"__newindex", lupb_Array_Newindex},
486
+ {NULL, NULL}};
487
+
488
+ /* lupb_map *******************************************************************/
489
+
490
+ typedef struct {
491
+ upb_Map* map;
492
+ upb_CType key_type;
493
+ upb_CType value_type;
494
+ } lupb_map;
495
+
496
+ #define MAP_MSGDEF_INDEX 1
497
+
498
+ static lupb_map* lupb_map_check(lua_State* L, int narg) {
499
+ return luaL_checkudata(L, narg, LUPB_MAP);
500
+ }
501
+
502
+ /* lupb_map Public API */
503
+
504
+ /**
505
+ * lupb_Map_New
506
+ *
507
+ * Handles:
508
+ * new_map = upb.Map(key_type, value_type)
509
+ * new_map = upb.Map(key_type, value_msgdef)
510
+ */
511
+ static int lupb_Map_New(lua_State* L) {
512
+ upb_Arena* arena;
513
+ lupb_map* lmap;
514
+
515
+ if (lua_type(L, 2) == LUA_TNUMBER) {
516
+ lmap = lupb_newuserdata(L, sizeof(*lmap), 1, LUPB_MAP);
517
+ lmap->value_type = lupb_checkfieldtype(L, 2);
518
+ } else {
519
+ lupb_MessageDef_check(L, 2);
520
+ lmap = lupb_newuserdata(L, sizeof(*lmap), 2, LUPB_MAP);
521
+ lmap->value_type = kUpb_CType_Message;
522
+ lua_pushvalue(L, 2);
523
+ lua_setiuservalue(L, -2, MAP_MSGDEF_INDEX);
524
+ }
525
+
526
+ arena = lupb_Arena_pushnew(L);
527
+ lua_setiuservalue(L, -2, LUPB_ARENA_INDEX);
528
+
529
+ lmap->key_type = lupb_checkfieldtype(L, 1);
530
+ lmap->map = upb_Map_New(arena, lmap->key_type, lmap->value_type);
531
+ lupb_cacheset(L, lmap->map);
532
+
533
+ return 1;
534
+ }
535
+
536
+ /**
537
+ * lupb_map_index
538
+ *
539
+ * Handles:
540
+ * map[key]
541
+ */
542
+ static int lupb_map_index(lua_State* L) {
543
+ lupb_map* lmap = lupb_map_check(L, 1);
544
+ upb_MessageValue key = lupb_tomsgval(L, lmap->key_type, 2, 1, LUPB_REF);
545
+ upb_MessageValue val;
546
+
547
+ if (upb_Map_Get(lmap->map, key, &val)) {
548
+ lupb_pushmsgval(L, 1, lmap->value_type, val);
549
+ } else {
550
+ lua_pushnil(L);
551
+ }
552
+
553
+ return 1;
554
+ }
555
+
556
+ /**
557
+ * lupb_map_len
558
+ *
559
+ * Handles:
560
+ * map_len = #map
561
+ */
562
+ static int lupb_map_len(lua_State* L) {
563
+ lupb_map* lmap = lupb_map_check(L, 1);
564
+ lua_pushnumber(L, upb_Map_Size(lmap->map));
565
+ return 1;
566
+ }
567
+
568
+ /**
569
+ * lupb_Map_Newindex
570
+ *
571
+ * Handles:
572
+ * map[key] = val
573
+ * map[key] = nil # to remove from map
574
+ */
575
+ static int lupb_Map_Newindex(lua_State* L) {
576
+ lupb_map* lmap = lupb_map_check(L, 1);
577
+ upb_Map* map = lmap->map;
578
+ upb_MessageValue key = lupb_tomsgval(L, lmap->key_type, 2, 1, LUPB_REF);
579
+
580
+ if (lua_isnil(L, 3)) {
581
+ upb_Map_Delete(map, key);
582
+ } else {
583
+ upb_MessageValue val = lupb_tomsgval(L, lmap->value_type, 3, 1, LUPB_COPY);
584
+ upb_Map_Set(map, key, val, lupb_Arenaget(L, 1));
585
+ if (lmap->value_type == kUpb_CType_Message) {
586
+ lupb_Arena_Fuseobjs(L, 1, 3);
587
+ }
588
+ }
589
+
590
+ return 0;
591
+ }
592
+
593
+ static int lupb_MapIterator_Next(lua_State* L) {
594
+ int map = lua_upvalueindex(2);
595
+ size_t* iter = lua_touserdata(L, lua_upvalueindex(1));
596
+ lupb_map* lmap = lupb_map_check(L, map);
597
+
598
+ if (upb_MapIterator_Next(lmap->map, iter)) {
599
+ upb_MessageValue key = upb_MapIterator_Key(lmap->map, *iter);
600
+ upb_MessageValue val = upb_MapIterator_Value(lmap->map, *iter);
601
+ lupb_pushmsgval(L, map, lmap->key_type, key);
602
+ lupb_pushmsgval(L, map, lmap->value_type, val);
603
+ return 2;
604
+ } else {
605
+ return 0;
606
+ }
607
+ }
608
+
609
+ /**
610
+ * lupb_map_pairs()
611
+ *
612
+ * Handles:
613
+ * pairs(map)
614
+ */
615
+ static int lupb_map_pairs(lua_State* L) {
616
+ size_t* iter = lua_newuserdata(L, sizeof(*iter));
617
+ lupb_map_check(L, 1);
618
+
619
+ *iter = kUpb_Map_Begin;
620
+ lua_pushvalue(L, 1);
621
+
622
+ /* Upvalues are [iter, lupb_map]. */
623
+ lua_pushcclosure(L, &lupb_MapIterator_Next, 2);
624
+
625
+ return 1;
626
+ }
627
+
628
+ /* upb_mapiter ]]] */
629
+
630
+ static const struct luaL_Reg lupb_map_mm[] = {{"__index", lupb_map_index},
631
+ {"__len", lupb_map_len},
632
+ {"__newindex", lupb_Map_Newindex},
633
+ {"__pairs", lupb_map_pairs},
634
+ {NULL, NULL}};
635
+
636
+ /* lupb_Message
637
+ * *******************************************************************/
638
+
639
+ typedef struct {
640
+ upb_Message* msg;
641
+ } lupb_Message;
642
+
643
+ /* lupb_Message helpers */
644
+
645
+ static upb_Message* lupb_msg_check(lua_State* L, int narg) {
646
+ lupb_Message* msg = luaL_checkudata(L, narg, LUPB_MSG);
647
+ return msg->msg;
648
+ }
649
+
650
+ static const upb_MessageDef* lupb_Message_Getmsgdef(lua_State* L, int msg) {
651
+ lua_getiuservalue(L, msg, LUPB_MSGDEF_INDEX);
652
+ const upb_MessageDef* m = lupb_MessageDef_check(L, -1);
653
+ lua_pop(L, 1);
654
+ return m;
655
+ }
656
+
657
+ static const upb_FieldDef* lupb_msg_tofield(lua_State* L, int msg, int field) {
658
+ size_t len;
659
+ const char* fieldname = luaL_checklstring(L, field, &len);
660
+ const upb_MessageDef* m = lupb_Message_Getmsgdef(L, msg);
661
+ return upb_MessageDef_FindFieldByNameWithSize(m, fieldname, len);
662
+ }
663
+
664
+ static const upb_FieldDef* lupb_msg_checkfield(lua_State* L, int msg,
665
+ int field) {
666
+ const upb_FieldDef* f = lupb_msg_tofield(L, msg, field);
667
+ if (f == NULL) {
668
+ luaL_error(L, "no such field '%s'", lua_tostring(L, field));
669
+ }
670
+ return f;
671
+ }
672
+
673
+ upb_Message* lupb_msg_pushnew(lua_State* L, int narg) {
674
+ const upb_MessageDef* m = lupb_MessageDef_check(L, narg);
675
+ lupb_Message* lmsg = lupb_newuserdata(L, sizeof(lupb_Message), 2, LUPB_MSG);
676
+ upb_Arena* arena = lupb_Arena_pushnew(L);
677
+
678
+ lua_setiuservalue(L, -2, LUPB_ARENA_INDEX);
679
+ lua_pushvalue(L, 1);
680
+ lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX);
681
+
682
+ lmsg->msg = upb_Message_New(m, arena);
683
+ lupb_cacheset(L, lmsg->msg);
684
+ return lmsg->msg;
685
+ }
686
+
687
+ /**
688
+ * lupb_Message_Newmsgwrapper()
689
+ *
690
+ * Creates a new wrapper for a message, copying the arena and msgdef references
691
+ * from |narg| (which should be an array or map).
692
+ */
693
+ static void lupb_Message_Newmsgwrapper(lua_State* L, int narg,
694
+ upb_MessageValue val) {
695
+ lupb_Message* lmsg = lupb_newuserdata(L, sizeof(*lmsg), 2, LUPB_MSG);
696
+ lmsg->msg = (upb_Message*)val.msg_val; /* XXX: cast isn't great. */
697
+ lupb_cacheset(L, lmsg->msg);
698
+
699
+ /* Copy both arena and msgdef into the wrapper. */
700
+ lua_getiuservalue(L, narg, LUPB_ARENA_INDEX);
701
+ lua_setiuservalue(L, -2, LUPB_ARENA_INDEX);
702
+ lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX);
703
+ lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX);
704
+ }
705
+
706
+ /**
707
+ * lupb_Message_Newud()
708
+ *
709
+ * Creates the Lua userdata for a new wrapper object, adding a reference to
710
+ * the msgdef if necessary.
711
+ */
712
+ static void* lupb_Message_Newud(lua_State* L, int narg, size_t size,
713
+ const char* type, const upb_FieldDef* f) {
714
+ if (upb_FieldDef_CType(f) == kUpb_CType_Message) {
715
+ /* Wrapper needs a reference to the msgdef. */
716
+ void* ud = lupb_newuserdata(L, size, 2, type);
717
+ lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX);
718
+ lupb_MessageDef_pushsubmsgdef(L, f);
719
+ lua_setiuservalue(L, -2, LUPB_MSGDEF_INDEX);
720
+ return ud;
721
+ } else {
722
+ return lupb_newuserdata(L, size, 1, type);
723
+ }
724
+ }
725
+
726
+ /**
727
+ * lupb_Message_Newwrapper()
728
+ *
729
+ * Creates a new Lua wrapper object to wrap the given array, map, or message.
730
+ */
731
+ static void lupb_Message_Newwrapper(lua_State* L, int narg,
732
+ const upb_FieldDef* f,
733
+ upb_MutableMessageValue val) {
734
+ if (upb_FieldDef_IsMap(f)) {
735
+ const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
736
+ const upb_FieldDef* key_f =
737
+ upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
738
+ const upb_FieldDef* val_f =
739
+ upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
740
+ lupb_map* lmap =
741
+ lupb_Message_Newud(L, narg, sizeof(*lmap), LUPB_MAP, val_f);
742
+ lmap->key_type = upb_FieldDef_CType(key_f);
743
+ lmap->value_type = upb_FieldDef_CType(val_f);
744
+ lmap->map = val.map;
745
+ } else if (upb_FieldDef_IsRepeated(f)) {
746
+ lupb_array* larr =
747
+ lupb_Message_Newud(L, narg, sizeof(*larr), LUPB_ARRAY, f);
748
+ larr->type = upb_FieldDef_CType(f);
749
+ larr->arr = val.array;
750
+ } else {
751
+ lupb_Message* lmsg =
752
+ lupb_Message_Newud(L, narg, sizeof(*lmsg), LUPB_MSG, f);
753
+ lmsg->msg = val.msg;
754
+ }
755
+
756
+ /* Copy arena ref to new wrapper. This may be a different arena than the
757
+ * underlying data was originally constructed from, but if so both arenas
758
+ * must be in the same group. */
759
+ lua_getiuservalue(L, narg, LUPB_ARENA_INDEX);
760
+ lua_setiuservalue(L, -2, LUPB_ARENA_INDEX);
761
+
762
+ lupb_cacheset(L, val.msg);
763
+ }
764
+
765
+ /**
766
+ * lupb_msg_typechecksubmsg()
767
+ *
768
+ * Typechecks the given array, map, or msg against this upb_FieldDef.
769
+ */
770
+ static void lupb_msg_typechecksubmsg(lua_State* L, int narg, int msgarg,
771
+ const upb_FieldDef* f) {
772
+ /* Typecheck this map's msgdef against this message field. */
773
+ lua_getiuservalue(L, narg, LUPB_MSGDEF_INDEX);
774
+ lua_getiuservalue(L, msgarg, LUPB_MSGDEF_INDEX);
775
+ lupb_MessageDef_pushsubmsgdef(L, f);
776
+ luaL_argcheck(L, lua_rawequal(L, -1, -2), narg, "message type mismatch");
777
+ lua_pop(L, 2);
778
+ }
779
+
780
+ /* lupb_Message Public API */
781
+
782
+ /**
783
+ * lupb_MessageDef_call
784
+ *
785
+ * Handles:
786
+ * new_msg = MessageClass()
787
+ * new_msg = MessageClass{foo = "bar", baz = 3, quux = {foo = 3}}
788
+ */
789
+ int lupb_MessageDef_call(lua_State* L) {
790
+ int arg_count = lua_gettop(L);
791
+ lupb_msg_pushnew(L, 1);
792
+
793
+ if (arg_count > 1) {
794
+ /* Set initial fields from table. */
795
+ int msg = arg_count + 1;
796
+ lua_pushnil(L);
797
+ while (lua_next(L, 2) != 0) {
798
+ lua_pushvalue(L, -2); /* now stack is key, val, key */
799
+ lua_insert(L, -3); /* now stack is key, key, val */
800
+ lua_settable(L, msg);
801
+ }
802
+ }
803
+
804
+ return 1;
805
+ }
806
+
807
+ /**
808
+ * lupb_msg_index
809
+ *
810
+ * Handles:
811
+ * msg.foo
812
+ * msg["foo"]
813
+ * msg[field_descriptor] # (for extensions) (TODO)
814
+ */
815
+ static int lupb_msg_index(lua_State* L) {
816
+ upb_Message* msg = lupb_msg_check(L, 1);
817
+ const upb_FieldDef* f = lupb_msg_checkfield(L, 1, 2);
818
+
819
+ if (upb_FieldDef_IsRepeated(f) || upb_FieldDef_IsSubMessage(f)) {
820
+ /* Wrapped type; get or create wrapper. */
821
+ upb_Arena* arena = upb_FieldDef_IsRepeated(f) ? lupb_Arenaget(L, 1) : NULL;
822
+ upb_MutableMessageValue val = upb_Message_Mutable(msg, f, arena);
823
+ if (!lupb_cacheget(L, val.msg)) {
824
+ lupb_Message_Newwrapper(L, 1, f, val);
825
+ }
826
+ } else {
827
+ /* Value type, just push value and return .*/
828
+ upb_MessageValue val = upb_Message_Get(msg, f);
829
+ lupb_pushmsgval(L, 0, upb_FieldDef_CType(f), val);
830
+ }
831
+
832
+ return 1;
833
+ }
834
+
835
+ /**
836
+ * lupb_Message_Newindex()
837
+ *
838
+ * Handles:
839
+ * msg.foo = bar
840
+ * msg["foo"] = bar
841
+ * msg[field_descriptor] = bar # (for extensions) (TODO)
842
+ */
843
+ static int lupb_Message_Newindex(lua_State* L) {
844
+ upb_Message* msg = lupb_msg_check(L, 1);
845
+ const upb_FieldDef* f = lupb_msg_checkfield(L, 1, 2);
846
+ upb_MessageValue msgval;
847
+ bool merge_arenas = true;
848
+
849
+ if (upb_FieldDef_IsMap(f)) {
850
+ lupb_map* lmap = lupb_map_check(L, 3);
851
+ const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
852
+ const upb_FieldDef* key_f =
853
+ upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
854
+ const upb_FieldDef* val_f =
855
+ upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
856
+ upb_CType key_type = upb_FieldDef_CType(key_f);
857
+ upb_CType value_type = upb_FieldDef_CType(val_f);
858
+ luaL_argcheck(L, lmap->key_type == key_type, 3, "key type mismatch");
859
+ luaL_argcheck(L, lmap->value_type == value_type, 3, "value type mismatch");
860
+ if (value_type == kUpb_CType_Message) {
861
+ lupb_msg_typechecksubmsg(L, 3, 1, val_f);
862
+ }
863
+ msgval.map_val = lmap->map;
864
+ } else if (upb_FieldDef_IsRepeated(f)) {
865
+ lupb_array* larr = lupb_array_check(L, 3);
866
+ upb_CType type = upb_FieldDef_CType(f);
867
+ luaL_argcheck(L, larr->type == type, 3, "array type mismatch");
868
+ if (type == kUpb_CType_Message) {
869
+ lupb_msg_typechecksubmsg(L, 3, 1, f);
870
+ }
871
+ msgval.array_val = larr->arr;
872
+ } else if (upb_FieldDef_IsSubMessage(f)) {
873
+ upb_Message* msg = lupb_msg_check(L, 3);
874
+ lupb_msg_typechecksubmsg(L, 3, 1, f);
875
+ msgval.msg_val = msg;
876
+ } else {
877
+ msgval = lupb_tomsgval(L, upb_FieldDef_CType(f), 3, 1, LUPB_COPY);
878
+ merge_arenas = false;
879
+ }
880
+
881
+ if (merge_arenas) {
882
+ lupb_Arena_Fuseobjs(L, 1, 3);
883
+ }
884
+
885
+ upb_Message_Set(msg, f, msgval, lupb_Arenaget(L, 1));
886
+
887
+ /* Return the new value for chained assignments. */
888
+ lua_pushvalue(L, 3);
889
+ return 1;
890
+ }
891
+
892
+ /**
893
+ * lupb_msg_tostring()
894
+ *
895
+ * Handles:
896
+ * tostring(msg)
897
+ * print(msg)
898
+ * etc.
899
+ */
900
+ static int lupb_msg_tostring(lua_State* L) {
901
+ upb_Message* msg = lupb_msg_check(L, 1);
902
+ const upb_MessageDef* m;
903
+ char buf[1024];
904
+ size_t size;
905
+
906
+ lua_getiuservalue(L, 1, LUPB_MSGDEF_INDEX);
907
+ m = lupb_MessageDef_check(L, -1);
908
+
909
+ size = upb_TextEncode(msg, m, NULL, 0, buf, sizeof(buf));
910
+
911
+ if (size < sizeof(buf)) {
912
+ lua_pushlstring(L, buf, size);
913
+ } else {
914
+ char* ptr = malloc(size + 1);
915
+ upb_TextEncode(msg, m, NULL, 0, ptr, size + 1);
916
+ lua_pushlstring(L, ptr, size);
917
+ free(ptr);
918
+ }
919
+
920
+ return 1;
921
+ }
922
+
923
+ static const struct luaL_Reg lupb_msg_mm[] = {
924
+ {"__index", lupb_msg_index},
925
+ {"__newindex", lupb_Message_Newindex},
926
+ {"__tostring", lupb_msg_tostring},
927
+ {NULL, NULL}};
928
+
929
+ /* lupb_Message toplevel
930
+ * **********************************************************/
931
+
932
+ static int lupb_getoptions(lua_State* L, int narg) {
933
+ int options = 0;
934
+ if (lua_gettop(L) >= narg) {
935
+ size_t len = lua_rawlen(L, narg);
936
+ for (size_t i = 1; i <= len; i++) {
937
+ lua_rawgeti(L, narg, i);
938
+ options |= lupb_checkuint32(L, -1);
939
+ lua_pop(L, 1);
940
+ }
941
+ }
942
+ return options;
943
+ }
944
+
945
+ /**
946
+ * lupb_decode()
947
+ *
948
+ * Handles:
949
+ * msg = upb.decode(MessageClass, bin_string)
950
+ */
951
+ static int lupb_decode(lua_State* L) {
952
+ size_t len;
953
+ const upb_MessageDef* m = lupb_MessageDef_check(L, 1);
954
+ const char* pb = lua_tolstring(L, 2, &len);
955
+ const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
956
+ upb_Message* msg = lupb_msg_pushnew(L, 1);
957
+ upb_Arena* arena = lupb_Arenaget(L, -1);
958
+ char* buf;
959
+
960
+ /* Copy input data to arena, message will reference it. */
961
+ buf = upb_Arena_Malloc(arena, len);
962
+ memcpy(buf, pb, len);
963
+
964
+ upb_DecodeStatus status = upb_Decode(buf, len, msg, layout, NULL,
965
+ kUpb_DecodeOption_AliasString, arena);
966
+
967
+ if (status != kUpb_DecodeStatus_Ok) {
968
+ lua_pushstring(L, "Error decoding protobuf.");
969
+ return lua_error(L);
970
+ }
971
+
972
+ return 1;
973
+ }
974
+
975
+ /**
976
+ * lupb_Encode()
977
+ *
978
+ * Handles:
979
+ * bin_string = upb.encode(msg)
980
+ */
981
+ static int lupb_Encode(lua_State* L) {
982
+ const upb_Message* msg = lupb_msg_check(L, 1);
983
+ const upb_MessageDef* m = lupb_Message_Getmsgdef(L, 1);
984
+ const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
985
+ int options = lupb_getoptions(L, 2);
986
+ upb_Arena* arena;
987
+ size_t size;
988
+ char* result;
989
+
990
+ arena = lupb_Arena_pushnew(L);
991
+ result = upb_Encode(msg, (const void*)layout, options, arena, &size);
992
+
993
+ if (!result) {
994
+ lua_pushstring(L, "Error encoding protobuf.");
995
+ return lua_error(L);
996
+ }
997
+
998
+ lua_pushlstring(L, result, size);
999
+
1000
+ return 1;
1001
+ }
1002
+
1003
+ /**
1004
+ * lupb_jsondecode()
1005
+ *
1006
+ * Handles:
1007
+ * text_string = upb.json_decode(MessageClass, json_str,
1008
+ * {upb.JSONDEC_IGNOREUNKNOWN})
1009
+ */
1010
+ static int lupb_jsondecode(lua_State* L) {
1011
+ size_t len;
1012
+ const upb_MessageDef* m = lupb_MessageDef_check(L, 1);
1013
+ const char* json = lua_tolstring(L, 2, &len);
1014
+ int options = lupb_getoptions(L, 3);
1015
+ upb_Message* msg;
1016
+ upb_Arena* arena;
1017
+ upb_Status status;
1018
+
1019
+ msg = lupb_msg_pushnew(L, 1);
1020
+ arena = lupb_Arenaget(L, -1);
1021
+ upb_Status_Clear(&status);
1022
+ upb_JsonDecode(json, len, msg, m, NULL, options, arena, &status);
1023
+ lupb_checkstatus(L, &status);
1024
+
1025
+ return 1;
1026
+ }
1027
+
1028
+ /**
1029
+ * lupb_jsonencode()
1030
+ *
1031
+ * Handles:
1032
+ * text_string = upb.json_encode(msg, {upb.JSONENC_EMITDEFAULTS})
1033
+ */
1034
+ static int lupb_jsonencode(lua_State* L) {
1035
+ upb_Message* msg = lupb_msg_check(L, 1);
1036
+ const upb_MessageDef* m = lupb_Message_Getmsgdef(L, 1);
1037
+ int options = lupb_getoptions(L, 2);
1038
+ char buf[1024];
1039
+ size_t size;
1040
+ upb_Status status;
1041
+
1042
+ upb_Status_Clear(&status);
1043
+ size = upb_JsonEncode(msg, m, NULL, options, buf, sizeof(buf), &status);
1044
+ lupb_checkstatus(L, &status);
1045
+
1046
+ if (size < sizeof(buf)) {
1047
+ lua_pushlstring(L, buf, size);
1048
+ } else {
1049
+ char* ptr = malloc(size + 1);
1050
+ upb_JsonEncode(msg, m, NULL, options, ptr, size + 1, &status);
1051
+ lupb_checkstatus(L, &status);
1052
+ lua_pushlstring(L, ptr, size);
1053
+ free(ptr);
1054
+ }
1055
+
1056
+ return 1;
1057
+ }
1058
+
1059
+ /**
1060
+ * lupb_textencode()
1061
+ *
1062
+ * Handles:
1063
+ * text_string = upb.text_encode(msg, {upb.TXTENC_SINGLELINE})
1064
+ */
1065
+ static int lupb_textencode(lua_State* L) {
1066
+ upb_Message* msg = lupb_msg_check(L, 1);
1067
+ const upb_MessageDef* m = lupb_Message_Getmsgdef(L, 1);
1068
+ int options = lupb_getoptions(L, 2);
1069
+ char buf[1024];
1070
+ size_t size;
1071
+
1072
+ size = upb_TextEncode(msg, m, NULL, options, buf, sizeof(buf));
1073
+
1074
+ if (size < sizeof(buf)) {
1075
+ lua_pushlstring(L, buf, size);
1076
+ } else {
1077
+ char* ptr = malloc(size + 1);
1078
+ upb_TextEncode(msg, m, NULL, options, ptr, size + 1);
1079
+ lua_pushlstring(L, ptr, size);
1080
+ free(ptr);
1081
+ }
1082
+
1083
+ return 1;
1084
+ }
1085
+
1086
+ static void lupb_setfieldi(lua_State* L, const char* field, int i) {
1087
+ lua_pushinteger(L, i);
1088
+ lua_setfield(L, -2, field);
1089
+ }
1090
+
1091
+ static const struct luaL_Reg lupb_msg_toplevel_m[] = {
1092
+ {"Array", lupb_Array_New}, {"Map", lupb_Map_New},
1093
+ {"decode", lupb_decode}, {"encode", lupb_Encode},
1094
+ {"json_decode", lupb_jsondecode}, {"json_encode", lupb_jsonencode},
1095
+ {"text_encode", lupb_textencode}, {NULL, NULL}};
1096
+
1097
+ void lupb_msg_registertypes(lua_State* L) {
1098
+ lupb_setfuncs(L, lupb_msg_toplevel_m);
1099
+
1100
+ lupb_register_type(L, LUPB_ARENA, NULL, lupb_Arena_mm);
1101
+ lupb_register_type(L, LUPB_ARRAY, NULL, lupb_array_mm);
1102
+ lupb_register_type(L, LUPB_MAP, NULL, lupb_map_mm);
1103
+ lupb_register_type(L, LUPB_MSG, NULL, lupb_msg_mm);
1104
+
1105
+ lupb_setfieldi(L, "TXTENC_SINGLELINE", UPB_TXTENC_SINGLELINE);
1106
+ lupb_setfieldi(L, "TXTENC_SKIPUNKNOWN", UPB_TXTENC_SKIPUNKNOWN);
1107
+ lupb_setfieldi(L, "TXTENC_NOSORT", UPB_TXTENC_NOSORT);
1108
+
1109
+ lupb_setfieldi(L, "ENCODE_DETERMINISTIC", kUpb_Encode_Deterministic);
1110
+ lupb_setfieldi(L, "ENCODE_SKIPUNKNOWN", kUpb_Encode_SkipUnknown);
1111
+
1112
+ lupb_setfieldi(L, "JSONENC_EMITDEFAULTS", upb_JsonEncode_EmitDefaults);
1113
+ lupb_setfieldi(L, "JSONENC_PROTONAMES", upb_JsonEncode_UseProtoNames);
1114
+
1115
+ lupb_setfieldi(L, "JSONDEC_IGNOREUNKNOWN", upb_JsonDecode_IgnoreUnknown);
1116
+
1117
+ lupb_cacheinit(L);
1118
+ }