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,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
+ }