hermes_messenger_of_the_gods 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.drone.yml +9 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +13 -0
  8. data/README.md +464 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/exe/fly_hermes +57 -0
  13. data/hermes_messenger_of_the_gods.gemspec +38 -0
  14. data/lib/hermes_messenger_of_the_gods.rb +57 -0
  15. data/lib/hermes_messenger_of_the_gods/concerns/base.rb +42 -0
  16. data/lib/hermes_messenger_of_the_gods/concerns/grpc_protobuf.rb +62 -0
  17. data/lib/hermes_messenger_of_the_gods/concerns/message.rb +194 -0
  18. data/lib/hermes_messenger_of_the_gods/concerns/mono_message.rb +52 -0
  19. data/lib/hermes_messenger_of_the_gods/concerns/worker.rb +173 -0
  20. data/lib/hermes_messenger_of_the_gods/configuration.rb +29 -0
  21. data/lib/hermes_messenger_of_the_gods/endpoint_builder.rb +41 -0
  22. data/lib/hermes_messenger_of_the_gods/endpoints.rb +3 -0
  23. data/lib/hermes_messenger_of_the_gods/endpoints/base.rb +113 -0
  24. data/lib/hermes_messenger_of_the_gods/endpoints/sns.rb +21 -0
  25. data/lib/hermes_messenger_of_the_gods/endpoints/sqs.rb +114 -0
  26. data/lib/hermes_messenger_of_the_gods/exceptions.rb +27 -0
  27. data/lib/hermes_messenger_of_the_gods/logging_helpers.rb +30 -0
  28. data/lib/hermes_messenger_of_the_gods/output/basic.rb +63 -0
  29. data/lib/hermes_messenger_of_the_gods/status_server.rb +48 -0
  30. data/lib/hermes_messenger_of_the_gods/testing/array_endpoint.rb +46 -0
  31. data/lib/hermes_messenger_of_the_gods/testing/dispatch_matcher.rb +52 -0
  32. data/lib/hermes_messenger_of_the_gods/testing/rspec_helpers.rb +64 -0
  33. data/lib/hermes_messenger_of_the_gods/version.rb +3 -0
  34. data/packageGems.sh +13 -0
  35. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.bundlecache +0 -0
  36. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.circleci/config.yml +32 -0
  37. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.gitignore +11 -0
  38. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.rspec +3 -0
  39. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.rubocop.yml +42 -0
  40. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.ruby-version +1 -0
  41. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/.travis.yml +5 -0
  42. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/Gemfile +6 -0
  43. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/Gemfile.lock +75 -0
  44. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/Makefile +1 -0
  45. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/README.md +78 -0
  46. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/Rakefile +6 -0
  47. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/bundle +105 -0
  48. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/coderay +29 -0
  49. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/console +14 -0
  50. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/grpc_tools_ruby_protoc +29 -0
  51. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/grpc_tools_ruby_protoc_plugin +29 -0
  52. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/htmldiff +29 -0
  53. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/ldiff +29 -0
  54. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/pry +29 -0
  55. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/rake +29 -0
  56. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/rspec +29 -0
  57. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/rubocop +29 -0
  58. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/ruby-parse +29 -0
  59. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/ruby-rewrite +29 -0
  60. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/bin/setup +8 -0
  61. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/lib/protobuf3_fixer.rb +123 -0
  62. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/lib/protobuf3_fixer/encoder.rb +63 -0
  63. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/lib/protobuf3_fixer/generation_helpers.rb +23 -0
  64. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/lib/protobuf3_fixer/reflector.rb +66 -0
  65. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/lib/protobuf3_fixer/version.rb +3 -0
  66. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/protobuf3_fixer.gemspec +54 -0
  67. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/bundle +105 -0
  68. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/coderay +29 -0
  69. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/grpc_tools_ruby_protoc +29 -0
  70. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/grpc_tools_ruby_protoc_plugin +29 -0
  71. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/htmldiff +29 -0
  72. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/ldiff +29 -0
  73. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/pry +29 -0
  74. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/rake +29 -0
  75. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/rspec +29 -0
  76. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/rubocop +29 -0
  77. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/ruby-parse +29 -0
  78. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/rubocop/ruby-rewrite +29 -0
  79. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/build_from_hash_spec.rb +20 -0
  80. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/encoding/encoding_options_spec.rb +23 -0
  81. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/extra_fields/json_decode_of_superset_spec.rb +54 -0
  82. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/generation_helpers_spec.rb +37 -0
  83. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/protobuf3_fixer_spec.rb +5 -0
  84. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/spec_helper.rb +17 -0
  85. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/support/compiled_protobuffs/source/superset_pb.rb +44 -0
  86. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/support/compiled_protobuffs/source/timestamp_pb.rb +27 -0
  87. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/support/protobuffs/source/superset.proto +40 -0
  88. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/support/protobuffs/source/timestamp.proto +18 -0
  89. data/vendor/cache/Protobuf3Fixer-5f9f1a2d2da9/spec/well_known_type_fixes/timestamp_spec.rb +79 -0
  90. data/vendor/cache/activemodel-6.0.3.1.gem +0 -0
  91. data/vendor/cache/activesupport-6.0.3.1.gem +0 -0
  92. data/vendor/cache/addressable-2.6.0.gem +0 -0
  93. data/vendor/cache/aws-eventstream-1.1.0.gem +0 -0
  94. data/vendor/cache/aws-partitions-1.329.0.gem +0 -0
  95. data/vendor/cache/aws-sdk-core-3.99.2.gem +0 -0
  96. data/vendor/cache/aws-sdk-sns-1.25.1.gem +0 -0
  97. data/vendor/cache/aws-sdk-sqs-1.27.1.gem +0 -0
  98. data/vendor/cache/aws-sigv4-1.1.4.gem +0 -0
  99. data/vendor/cache/codeclimate-test-reporter-1.0.9.gem +0 -0
  100. data/vendor/cache/coderay-1.1.2.gem +0 -0
  101. data/vendor/cache/concurrent-ruby-1.1.6.gem +0 -0
  102. data/vendor/cache/crack-0.4.3.gem +0 -0
  103. data/vendor/cache/diff-lcs-1.3.gem +0 -0
  104. data/vendor/cache/docile-1.1.5.gem +0 -0
  105. data/vendor/cache/google-protobuf-3.12.2-universal-darwin.gem +0 -0
  106. data/vendor/cache/google-protobuf-3.12.2-x86_64-linux.gem +0 -0
  107. data/vendor/cache/google-protobuf-3.12.2.gem +0 -0
  108. data/vendor/cache/googleapis-common-protos-types-1.0.2.gem +0 -0
  109. data/vendor/cache/grpc-1.18.0-universal-darwin.gem +0 -0
  110. data/vendor/cache/grpc-1.18.0-x86_64-linux.gem +0 -0
  111. data/vendor/cache/grpc-1.18.0.gem +0 -0
  112. data/vendor/cache/hashdiff-0.3.8.gem +0 -0
  113. data/vendor/cache/i18n-1.8.3.gem +0 -0
  114. data/vendor/cache/jmespath-1.4.0.gem +0 -0
  115. data/vendor/cache/json-2.1.0.gem +0 -0
  116. data/vendor/cache/memory_profiler-0.9.12.gem +0 -0
  117. data/vendor/cache/method_source-0.9.2.gem +0 -0
  118. data/vendor/cache/minitest-5.14.1.gem +0 -0
  119. data/vendor/cache/pry-0.12.2.gem +0 -0
  120. data/vendor/cache/public_suffix-3.0.3.gem +0 -0
  121. data/vendor/cache/rake-10.5.0.gem +0 -0
  122. data/vendor/cache/rspec-3.8.0.gem +0 -0
  123. data/vendor/cache/rspec-core-3.8.0.gem +0 -0
  124. data/vendor/cache/rspec-expectations-3.8.2.gem +0 -0
  125. data/vendor/cache/rspec-mocks-3.8.0.gem +0 -0
  126. data/vendor/cache/rspec-support-3.8.0.gem +0 -0
  127. data/vendor/cache/safe_yaml-1.0.4.gem +0 -0
  128. data/vendor/cache/simplecov-0.13.0.gem +0 -0
  129. data/vendor/cache/simplecov-html-0.10.2.gem +0 -0
  130. data/vendor/cache/thor-1.0.1.gem +0 -0
  131. data/vendor/cache/thread_safe-0.3.6.gem +0 -0
  132. data/vendor/cache/timecop-0.9.1.gem +0 -0
  133. data/vendor/cache/tzinfo-1.2.7.gem +0 -0
  134. data/vendor/cache/webmock-3.5.1.gem +0 -0
  135. data/vendor/cache/zeitwerk-2.3.0.gem +0 -0
  136. metadata +362 -0
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'pry' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("pry", "pry")
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'ruby-parse' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("parser", "ruby-parse")
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'ruby-rewrite' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("parser", "ruby-rewrite")
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'date'
5
+ require 'google/protobuf/well_known_types'
6
+ require 'google/type/date_pb'
7
+
8
+ require 'protobuf3_fixer/version'
9
+ require 'protobuf3_fixer/reflector'
10
+ require 'protobuf3_fixer/encoder'
11
+ require 'protobuf3_fixer/generation_helpers'
12
+
13
+ module Protobuf3Fixer
14
+ class << self
15
+ def reflect_on(klass)
16
+ @reflectors ||= Hash.new do |h, k|
17
+ h[k] = Protobuf3Fixer::Reflector.new(k)
18
+ end
19
+
20
+ @reflectors[klass]
21
+ end
22
+
23
+ def encode_json(instance, options = {})
24
+ fixed_transmission_hash(instance, options).to_json
25
+ end
26
+
27
+ def decode_json(klass, json)
28
+ build_from_hash(klass, JSON.parse(json), clean: true)
29
+ end
30
+
31
+ def fixed_transmission_hash(instance, options = {})
32
+ generated_json_hash = JSON.parse(instance.class.encode_json(instance, options))
33
+
34
+ Protobuf3Fixer::Encoder.new(
35
+ instance.class,
36
+ generated_json_hash
37
+ ).reencoded_hash
38
+ end
39
+
40
+ def build_from_hash(klass, hash_data, clean: false)
41
+ cleaned_obj = clean_json_data_for_klass(klass, deep_stringify_keys(hash_data), clean: clean)
42
+ klass.decode_json(cleaned_obj.to_json)
43
+ end
44
+
45
+ private
46
+
47
+ def deep_stringify_keys(hash_data)
48
+ hash_data.each_with_object({}) do |(k, v), hsh|
49
+ hsh[k.to_s] = v.is_a?(Hash) ? deep_stringify_keys(v) : v
50
+ end
51
+ end
52
+
53
+ def rework_for_well_known_types(klass, data)
54
+ data
55
+ end
56
+
57
+ def clean_json_data_for_klass(klass, data, clean: true)
58
+ data = rework_for_well_known_types(klass, data)
59
+ return data unless data.is_a?(Hash)
60
+
61
+ reflector = reflect_on(klass)
62
+
63
+ # Remove unknown fields
64
+ known_fields = prune_and_organize_fields(reflector, data, clean: clean)
65
+
66
+ final_data = {}
67
+
68
+ known_fields.each do |(json_field, ruby_field), original_value|
69
+ subklass = reflector.subklass_for(ruby_field)
70
+
71
+ if subklass
72
+ data = parse_data_for_subklass(
73
+ subklass,
74
+ reflector.field_type(ruby_field),
75
+ original_value
76
+ )
77
+ final_data[json_field] = data if data
78
+ else
79
+ final_data[json_field] = original_value
80
+ end
81
+ end
82
+
83
+ final_data
84
+ end
85
+
86
+ def parse_data_for_subklass(subklass, type, data)
87
+ case type
88
+ when Protobuf3Fixer::Reflector::TYPE_ARRAY
89
+ data.collect do |sub_object|
90
+ clean_json_data_for_klass(subklass, sub_object)
91
+ end
92
+ when Protobuf3Fixer::Reflector::TYPE_MAP
93
+ data.each_with_object({}) do |(map_key, sub_object), new_hash|
94
+ new_hash[map_key] = clean_json_data_for_klass(subklass, sub_object)
95
+ new_hash
96
+ end
97
+ when Protobuf3Fixer::Reflector::TYPE_SUB_OBJECT
98
+ clean_json_data_for_klass(subklass, data) if data
99
+ end
100
+ end
101
+
102
+ def prune_and_organize_fields(reflector, data, clean: true)
103
+ data.each_with_object({}) do |(k, v), fields|
104
+ json_field_name = k
105
+ local_field_name = if reflector.field_names.include?(rubyized_field_name(k))
106
+ rubyized_field_name(k)
107
+ elsif reflector.field_names.include?(k)
108
+ k
109
+ end
110
+
111
+ next if clean && !local_field_name
112
+
113
+ local_field_name ||= json_field_name
114
+
115
+ fields[[json_field_name, local_field_name]] = v
116
+ end
117
+ end
118
+
119
+ def rubyized_field_name(field_name)
120
+ field_name.gsub(/([a-z\d])([A-Z])/, '\1_\2').tap(&:downcase!)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,63 @@
1
+ require 'google/protobuf/well_known_types'
2
+
3
+ module Protobuf3Fixer
4
+ class Encoder
5
+ attr_accessor :klass, :data, :reflector
6
+ def initialize(klass, data)
7
+ self.klass = klass
8
+ self.data = data
9
+ self.reflector = Protobuf3Fixer.reflect_on(klass)
10
+ end
11
+
12
+ def reencoded_hash
13
+ clean_encoded_json_for_klass
14
+ end
15
+
16
+ private
17
+
18
+ def clean_encoded_json_for_klass
19
+ case required_typefix
20
+ when :timestamp
21
+ data
22
+ else
23
+ deep_parse_object
24
+ end
25
+ end
26
+
27
+ def deep_parse_object
28
+ data.each_with_object({}) do |(k, v), hsh|
29
+ rb_field_name = rubyized_field_name(k)
30
+ klass = reflector.subklass_for(k) || reflector.subklass_for(rb_field_name)
31
+ type = reflector.field_type(k) || reflector.field_type(rb_field_name)
32
+ hsh[k] = parse_value_for_type(klass, type, v)
33
+ end
34
+ end
35
+
36
+ def parse_value_for_type(klass, type, value)
37
+ case type
38
+ when Protobuf3Fixer::Reflector::TYPE_ARRAY
39
+ value.collect do |array_item|
40
+ self.class.new(klass, array_item).reencoded_hash
41
+ end
42
+ when Protobuf3Fixer::Reflector::TYPE_MAP
43
+ value.each_with_object({}) do |(map_key, sub_object), new_hash|
44
+ new_hash[map_key] = self.class.new(klass, sub_object).reencoded_hash
45
+ end
46
+ when Protobuf3Fixer::Reflector::TYPE_SUB_OBJECT
47
+ self.class.new(klass, value).reencoded_hash
48
+ else
49
+ value
50
+ end
51
+ end
52
+
53
+ def required_typefix
54
+ if klass == Google::Protobuf::Timestamp
55
+ :timestamp
56
+ end
57
+ end
58
+
59
+ def rubyized_field_name(field_name)
60
+ field_name.gsub(/([a-z\d])([A-Z])/, '\1_\2').tap(&:downcase!)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Protobuf3Fixer
6
+ module GenerationHelpers
7
+ TIMESTAMP = Google::Protobuf::DescriptorPool.generated_pool.lookup('google.protobuf.Timestamp').msgclass
8
+ DATE = Google::Protobuf::DescriptorPool.generated_pool.lookup('google.type.Date').msgclass
9
+
10
+ def self.create_timestamp(stmp)
11
+ TIMESTAMP.new.tap { |t| t.from_time(stmp) }
12
+ end
13
+
14
+ def self.create_date(date)
15
+ date = Date.parse(date) if date.is_a? String
16
+ DATE.new.tap do |d|
17
+ d.year = date.year
18
+ d.month = date.month
19
+ d.day = date.day
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Protobuf3Fixer
4
+ class Reflector
5
+ TYPE_PLAIN = :plain
6
+ TYPE_ARRAY = :array
7
+ TYPE_MAP = :map
8
+ TYPE_SUB_OBJECT = :subobject
9
+
10
+ attr_accessor :klass, :instance, :field_info, :field_names
11
+ def initialize(klass)
12
+ self.klass = klass
13
+ reflect!
14
+ end
15
+
16
+ def reflect!
17
+ self.field_info = {}
18
+ self.field_names = Set.new
19
+
20
+ self.instance = klass.new
21
+ klass.descriptor.each(&method(:reflect_on_field))
22
+ end
23
+
24
+ def field_type(field_name)
25
+ field_info[field_name][:type] if field_info[field_name]
26
+ end
27
+
28
+ def subklass_for(field_name)
29
+ field_info[field_name] && field_info[field_name][:klass]
30
+ end
31
+
32
+ def reflect_on_field(desc)
33
+ type = if desc.type == :message
34
+ determine_complex_type(instance.public_send(desc.name))
35
+ else
36
+ TYPE_PLAIN
37
+ end
38
+
39
+ field_names << desc.name
40
+ field_info[desc.name] = {
41
+ klass: divine_type(type, desc),
42
+ type: type,
43
+ }
44
+ end
45
+
46
+ def divine_type(type, descriptor)
47
+ case type
48
+ when TYPE_MAP
49
+ descriptor.subtype.to_a[1].subtype&.msgclass
50
+ when TYPE_ARRAY, TYPE_SUB_OBJECT
51
+ descriptor.subtype&.msgclass
52
+ end
53
+ end
54
+
55
+ def determine_complex_type(result)
56
+ case result
57
+ when Google::Protobuf::RepeatedField
58
+ TYPE_ARRAY
59
+ when Google::Protobuf::Map
60
+ TYPE_MAP
61
+ else
62
+ TYPE_SUB_OBJECT
63
+ end
64
+ end
65
+ end
66
+ end