protobuf 3.7.0.pre2 → 3.7.0.pre3

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/.rubocop_todo.yml +7 -1
  4. data/.travis.yml +8 -1
  5. data/CHANGES.md +25 -1
  6. data/bin/protoc-gen-ruby +2 -2
  7. data/lib/protobuf/cli.rb +29 -17
  8. data/lib/protobuf/code_generator.rb +49 -1
  9. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +9 -1
  10. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +14 -1
  11. data/lib/protobuf/encoder.rb +2 -2
  12. data/lib/protobuf/enum.rb +3 -3
  13. data/lib/protobuf/field/base_field.rb +27 -19
  14. data/lib/protobuf/field/bool_field.rb +10 -8
  15. data/lib/protobuf/field/bytes_field.rb +14 -6
  16. data/lib/protobuf/field/float_field.rb +2 -0
  17. data/lib/protobuf/field/string_field.rb +10 -0
  18. data/lib/protobuf/field/varint_field.rb +12 -2
  19. data/lib/protobuf/generators/base.rb +29 -14
  20. data/lib/protobuf/generators/enum_generator.rb +4 -7
  21. data/lib/protobuf/generators/field_generator.rb +17 -4
  22. data/lib/protobuf/generators/file_generator.rb +121 -10
  23. data/lib/protobuf/generators/group_generator.rb +9 -3
  24. data/lib/protobuf/generators/message_generator.rb +8 -2
  25. data/lib/protobuf/generators/option_generator.rb +17 -0
  26. data/lib/protobuf/generators/printable.rb +2 -2
  27. data/lib/protobuf/generators/service_generator.rb +27 -3
  28. data/lib/protobuf/lifecycle.rb +1 -1
  29. data/lib/protobuf/message/fields.rb +13 -15
  30. data/lib/protobuf/message/serialization.rb +9 -9
  31. data/lib/protobuf/message.rb +23 -29
  32. data/lib/protobuf/optionable.rb +10 -10
  33. data/lib/protobuf/rpc/buffer.rb +7 -6
  34. data/lib/protobuf/rpc/client.rb +2 -30
  35. data/lib/protobuf/rpc/connectors/base.rb +168 -6
  36. data/lib/protobuf/rpc/connectors/ping.rb +2 -2
  37. data/lib/protobuf/rpc/connectors/socket.rb +6 -1
  38. data/lib/protobuf/rpc/connectors/zmq.rb +1 -2
  39. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +2 -1
  40. data/lib/protobuf/rpc/error.rb +2 -2
  41. data/lib/protobuf/rpc/middleware/exception_handler.rb +4 -0
  42. data/lib/protobuf/rpc/middleware/logger.rb +4 -0
  43. data/lib/protobuf/rpc/middleware/request_decoder.rb +11 -16
  44. data/lib/protobuf/rpc/middleware/response_encoder.rb +18 -23
  45. data/lib/protobuf/rpc/rpc.pb.rb +2 -1
  46. data/lib/protobuf/rpc/rpc_method.rb +16 -0
  47. data/lib/protobuf/rpc/servers/socket/server.rb +4 -4
  48. data/lib/protobuf/rpc/servers/socket_runner.rb +8 -0
  49. data/lib/protobuf/rpc/servers/zmq/broker.rb +7 -6
  50. data/lib/protobuf/rpc/servers/zmq/server.rb +8 -7
  51. data/lib/protobuf/rpc/servers/zmq/util.rb +6 -6
  52. data/lib/protobuf/rpc/servers/zmq/worker.rb +7 -6
  53. data/lib/protobuf/rpc/servers/zmq_runner.rb +8 -0
  54. data/lib/protobuf/rpc/service.rb +6 -15
  55. data/lib/protobuf/rpc/service_directory.rb +1 -1
  56. data/lib/protobuf/rpc/service_dispatcher.rb +5 -6
  57. data/lib/protobuf/rpc/service_filters.rb +8 -30
  58. data/lib/protobuf/socket.rb +2 -2
  59. data/lib/protobuf/version.rb +1 -1
  60. data/lib/protobuf/zmq.rb +2 -2
  61. data/lib/protobuf.rb +12 -27
  62. data/protobuf.gemspec +5 -3
  63. data/spec/benchmark/tasks.rb +1 -0
  64. data/spec/functional/code_generator_spec.rb +38 -0
  65. data/spec/lib/protobuf/cli_spec.rb +19 -10
  66. data/spec/lib/protobuf/code_generator_spec.rb +28 -0
  67. data/spec/lib/protobuf/enum_spec.rb +6 -2
  68. data/spec/lib/protobuf/field/bool_field_spec.rb +4 -0
  69. data/spec/lib/protobuf/field/double_field_spec.rb +9 -0
  70. data/spec/lib/protobuf/field/fixed32_field_spec.rb +7 -0
  71. data/spec/lib/protobuf/field/fixed64_field_spec.rb +7 -0
  72. data/spec/lib/protobuf/field/float_field_spec.rb +5 -1
  73. data/spec/lib/protobuf/field/int64_field_spec.rb +7 -0
  74. data/spec/lib/protobuf/field/message_field_spec.rb +53 -0
  75. data/spec/lib/protobuf/field/sfixed32_field_spec.rb +9 -0
  76. data/spec/lib/protobuf/field/sfixed64_field_spec.rb +9 -0
  77. data/spec/lib/protobuf/field/sint32_field_spec.rb +9 -0
  78. data/spec/lib/protobuf/field/sint64_field_spec.rb +9 -0
  79. data/spec/lib/protobuf/field/uint32_field_spec.rb +7 -0
  80. data/spec/lib/protobuf/field/uint64_field_spec.rb +7 -0
  81. data/spec/lib/protobuf/generators/base_spec.rb +69 -1
  82. data/spec/lib/protobuf/generators/enum_generator_spec.rb +1 -1
  83. data/spec/lib/protobuf/generators/field_generator_spec.rb +58 -0
  84. data/spec/lib/protobuf/generators/file_generator_spec.rb +47 -0
  85. data/spec/lib/protobuf/generators/service_generator_spec.rb +58 -14
  86. data/spec/lib/protobuf/message_spec.rb +2 -2
  87. data/spec/lib/protobuf/optionable_spec.rb +96 -0
  88. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +151 -0
  89. data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +3 -3
  90. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +0 -2
  91. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +2 -2
  92. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +4 -4
  93. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +2 -2
  94. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +1 -18
  95. data/spec/lib/protobuf/rpc/service_filters_spec.rb +2 -2
  96. data/spec/lib/protobuf/varint_spec.rb +1 -1
  97. data/spec/lib/protobuf_spec.rb +13 -16
  98. data/spec/support/packed_field.rb +3 -2
  99. data/spec/support/protos/enum.pb.rb +2 -1
  100. data/spec/support/protos/enum.proto +1 -0
  101. data/spec/support/protos/google_unittest.pb.rb +69 -58
  102. data/spec/support/protos/google_unittest_custom_options.bin +0 -0
  103. data/spec/support/protos/google_unittest_custom_options.pb.rb +361 -0
  104. data/spec/support/protos/google_unittest_custom_options.proto +424 -0
  105. data/spec/support/protos/google_unittest_import.pb.rb +8 -0
  106. data/spec/support/protos/google_unittest_import_public.pb.rb +6 -0
  107. data/spec/support/protos/resource.pb.rb +54 -2
  108. data/spec/support/protos/resource.proto +42 -2
  109. data/spec/support/server.rb +1 -1
  110. metadata +39 -16
  111. data/lib/protobuf/rpc/connector.rb +0 -19
  112. data/lib/protobuf/rpc/connectors/common.rb +0 -176
  113. data/spec/lib/protobuf/rpc/connector_spec.rb +0 -26
  114. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +0 -170
@@ -15,16 +15,10 @@ module Protobuf
15
15
  end
16
16
 
17
17
  unless ENV.key?('PB_NO_TAG_WARNINGS')
18
- range = (tags.min)..(tags.max)
19
- if range.respond_to?(:size)
20
- expected_size = range.size
21
- else
22
- expected_size = range.to_a.size
23
- end
24
-
18
+ expected_size = tags.max - tags.min + 1
25
19
  if tags.size < expected_size
26
20
  ::Protobuf::CodeGenerator.print_tag_warning_suppress
27
- ::Protobuf::CodeGenerator.warn("#{type_name} object should have #{expected_size} tags (#{range.begin}..#{range.end}), but found #{tags.size} tags.")
21
+ ::Protobuf::CodeGenerator.warn("#{type_name} object should have #{expected_size} tags (#{tags.min}..#{tags.max}), but found #{tags.size} tags.")
28
22
  end
29
23
  end
30
24
  end
@@ -42,18 +36,18 @@ module Protobuf
42
36
  ".#{type_namespace.join('.')}"
43
37
  end
44
38
 
45
- def run_once(label, &block)
39
+ def run_once(label)
46
40
  tracker_ivar = "@_#{label}_compiled"
47
41
  value_ivar = "@_#{label}_compiled_value"
48
42
 
49
43
  if instance_variable_get(tracker_ivar)
50
44
  return instance_variable_get(value_ivar)
51
- else
52
- return_value = block.call
53
- instance_variable_set(tracker_ivar, true)
54
- instance_variable_set(value_ivar, return_value)
55
- return return_value
56
45
  end
46
+
47
+ return_value = yield
48
+ instance_variable_set(tracker_ivar, true)
49
+ instance_variable_set(value_ivar, return_value)
50
+ return_value
57
51
  end
58
52
 
59
53
  def to_s
@@ -65,6 +59,27 @@ module Protobuf
65
59
  @type_namespace ||= @namespace + [descriptor.name]
66
60
  end
67
61
 
62
+ def serialize_value(value)
63
+ case value
64
+ when Message
65
+ fields = value.each_field.map do |field, inner_value|
66
+ next unless value.field?(field.name)
67
+ serialized_inner_value = serialize_value(inner_value)
68
+ "#{field.fully_qualified_name.inspect} => #{serialized_inner_value}"
69
+ end.compact
70
+ "{ #{fields.join(', ')} }"
71
+ when Enum
72
+ "::#{value.parent_class}::#{value.name}"
73
+ when String
74
+ value.inspect
75
+ when nil
76
+ "nil"
77
+ when Array
78
+ '[' + value.map { |x| serialize_value(x) }.join(', ') + ']'
79
+ else
80
+ value
81
+ end
82
+ end
68
83
  end
69
84
  end
70
85
  end
@@ -1,20 +1,17 @@
1
1
  require 'protobuf/generators/base'
2
+ require 'protobuf/generators/option_generator'
2
3
 
3
4
  module Protobuf
4
5
  module Generators
5
6
  class EnumGenerator < Base
6
7
 
7
- def allow_alias?
8
- descriptor.options.try(:allow_alias!) { false }
9
- end
10
-
11
8
  def compile
12
9
  run_once(:compile) do
13
10
  tags = []
14
11
 
15
12
  print_class(descriptor.name, :enum) do
16
- if allow_alias?
17
- puts "set_option :allow_alias"
13
+ if descriptor.options
14
+ print OptionGenerator.new(descriptor.options, current_indent).to_s
18
15
  puts
19
16
  end
20
17
 
@@ -24,7 +21,7 @@ module Protobuf
24
21
  end
25
22
  end
26
23
 
27
- unless allow_alias?
24
+ unless descriptor.options.try(:allow_alias)
28
25
  self.class.validate_tags(fully_qualified_type_namespace, tags)
29
26
  end
30
27
  end
@@ -7,9 +7,9 @@ module Protobuf
7
7
  ##
8
8
  # Constants
9
9
  #
10
- PROTO_INFINITY_DEFAULT = /^inf$/i.freeze
11
- PROTO_NEGATIVE_INFINITY_DEFAULT = /^-inf$/i.freeze
12
- PROTO_NAN_DEFAULT = /^nan$/i.freeze
10
+ PROTO_INFINITY_DEFAULT = /^inf$/i
11
+ PROTO_NEGATIVE_INFINITY_DEFAULT = /^-inf$/i
12
+ PROTO_NAN_DEFAULT = /^nan$/i
13
13
  RUBY_INFINITY_DEFAULT = '::Float::INFINITY'.freeze
14
14
  RUBY_NEGATIVE_INFINITY_DEFAULT = '-::Float::INFINITY'.freeze
15
15
  RUBY_NAN_DEFAULT = '::Float::NAN'.freeze
@@ -84,6 +84,13 @@ module Protobuf
84
84
  opts[:packed] = 'true' if packed?
85
85
  opts[:deprecated] = 'true' if deprecated?
86
86
  opts[:extension] = 'true' if extension?
87
+ if descriptor.options
88
+ descriptor.options.each_field do |field_option|
89
+ next unless descriptor.options.field?(field_option.name)
90
+ option_value = descriptor.options[field_option.name]
91
+ opts[field_option.fully_qualified_name] = serialize_value(option_value)
92
+ end
93
+ end
87
94
  opts
88
95
  end
89
96
  end
@@ -108,7 +115,13 @@ module Protobuf
108
115
  private
109
116
 
110
117
  def enum_default_value
111
- "#{type_name}::#{verbatim_default_value}"
118
+ optionally_upcased_default =
119
+ if ENV.key?('PB_UPCASE_ENUMS')
120
+ verbatim_default_value.upcase
121
+ else
122
+ verbatim_default_value
123
+ end
124
+ "#{type_name}::#{optionally_upcased_default}"
112
125
  end
113
126
 
114
127
  def float_double_default_value
@@ -12,7 +12,8 @@ module Protobuf
12
12
  super
13
13
  @output_file = ::Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(:name => file_name)
14
14
  @extension_fields = Hash.new { |h, k| h[k] = [] }
15
- @known_messages = []
15
+ @known_messages = {}
16
+ @known_enums = {}
16
17
  @dangling_messages = {}
17
18
  end
18
19
 
@@ -31,6 +32,7 @@ module Protobuf
31
32
  print_package do
32
33
  inject_optionable
33
34
  group = GroupGenerator.new(current_indent)
35
+ group.add_options(descriptor.options) if descriptor.options
34
36
  group.add_enums(descriptor.enum_type, :namespace => [descriptor.package])
35
37
  group.add_message_declarations(descriptor.message_type)
36
38
  group.add_messages(descriptor.message_type, :extension_fields => @extension_fields, :namespace => [descriptor.package])
@@ -39,6 +41,7 @@ module Protobuf
39
41
 
40
42
  group.add_header(:enum, 'Enum Classes')
41
43
  group.add_header(:message_declaration, 'Message Classes')
44
+ group.add_header(:options, 'File Options')
42
45
  group.add_header(:message, 'Message Fields')
43
46
  group.add_header(:extended_message, 'Extended Message Fields')
44
47
  group.add_header(:service, 'Service Classes')
@@ -49,8 +52,16 @@ module Protobuf
49
52
  end
50
53
 
51
54
  def unknown_extensions
52
- @unknown_extensions ||= @extension_fields.reject do |k, _|
53
- @known_messages.include?(k)
55
+ @unknown_extensions ||= @extension_fields.map do |message_name, fields|
56
+ message_klass = modulize(message_name).safe_constantize
57
+ if message_klass
58
+ unknown_fields = fields.reject do |field|
59
+ @known_messages[message_name] && message_klass.get_field(field.name, true)
60
+ end
61
+ [message_name, unknown_fields]
62
+ else
63
+ [message_name, fields]
64
+ end
54
65
  end
55
66
  end
56
67
 
@@ -72,12 +83,10 @@ module Protobuf
72
83
  end
73
84
  # Record all the message descriptor name's we encounter (should be the whole tree).
74
85
  if descriptor.is_a?(::Google::Protobuf::DescriptorProto)
75
- if fully_qualified_token?(descriptor.name)
76
- @known_messages << descriptor.name
77
- else
78
- fully_qualified_namespace = ".#{namespaces.join('.')}"
79
- @known_messages << fully_qualified_namespace
80
- end
86
+ @known_messages[fully_qualified_namespace || descriptor.name] = descriptor
87
+ elsif descriptor.is_a?(::Google::Protobuf::EnumDescriptorProto)
88
+ @known_enums[fully_qualified_namespace || descriptor.name] = descriptor
89
+ return
81
90
  end
82
91
 
83
92
  descriptor.extension.each do |field_descriptor|
@@ -87,7 +96,7 @@ module Protobuf
87
96
  @extension_fields[field_descriptor.extendee] << field_descriptor
88
97
  end
89
98
 
90
- [:message_type, :nested_type].each do |type|
99
+ [:message_type, :nested_type, :enum_type].each do |type|
91
100
  next unless descriptor.respond_to_has_and_present?(type)
92
101
 
93
102
  descriptor.public_send(type).each do |type_descriptor|
@@ -132,6 +141,38 @@ module Protobuf
132
141
  end.call
133
142
  end
134
143
 
144
+ def eval_unknown_extensions!
145
+ @@evaled_dependencies ||= Set.new # rubocop:disable Style/ClassVars
146
+ @@all_messages ||= {} # rubocop:disable Style/ClassVars
147
+ @@all_enums ||= {} # rubocop:disable Style/ClassVars
148
+
149
+ map_extensions(descriptor, [descriptor.package])
150
+ @known_messages.each do |name, descriptor|
151
+ @@all_messages[name] = descriptor
152
+ end
153
+ @known_enums.each do |name, descriptor|
154
+ @@all_enums[name] = descriptor
155
+ end
156
+
157
+ # create package namespace
158
+ print_package {}
159
+ eval_code
160
+
161
+ unknown_extensions.each do |extendee, fields|
162
+ eval_dependencies(extendee)
163
+ fields.each do |field|
164
+ eval_dependencies(field.type_name)
165
+ end
166
+ end
167
+ group = GroupGenerator.new(0)
168
+ group.add_extended_messages(unknown_extensions, false)
169
+ print group.to_s
170
+ eval_code
171
+ rescue => e
172
+ warn "Error loading unknown extensions #{descriptor.name.inspect} error=#{e}"
173
+ raise e
174
+ end
175
+
135
176
  private
136
177
 
137
178
  def convert_filename(filename, for_require = true)
@@ -142,6 +183,76 @@ module Protobuf
142
183
  token[0] == '.'
143
184
  end
144
185
 
186
+ def eval_dependencies(name, namespace = nil)
187
+ name = "#{namespace}.#{name}" if namespace && !fully_qualified_token?(name)
188
+ return if name.empty? || @@evaled_dependencies.include?(name) || modulize(name).safe_constantize
189
+
190
+ # if name = .foo.bar.Baz look for classes / modules named ::Foo::Bar and ::Foo
191
+ # module == pure namespace (e.g. the descriptor package name)
192
+ # class == nested messages
193
+ create_ruby_namespace_heiarchy(name)
194
+
195
+ if (message = @@all_messages[name])
196
+ # Create the blank namespace in case there are nested types
197
+ eval_message_code(name)
198
+
199
+ message.nested_type.each do |nested_type|
200
+ eval_dependencies(nested_type.name, name) unless nested_type.name.empty?
201
+ end
202
+ message.field.each do |field|
203
+ eval_dependencies(field.type_name, name) unless field.type_name.empty?
204
+ end
205
+ message.enum_type.each do |enum_type|
206
+ eval_dependencies(enum_type.name, name)
207
+ end
208
+
209
+ # Check @@evaled_dependencies again in case there was a dependency
210
+ # loop that already loaded this message
211
+ return if @@evaled_dependencies.include?(name)
212
+ eval_message_code(name, message.field)
213
+ @@evaled_dependencies << name
214
+
215
+ elsif (enum = @@all_enums[name])
216
+ # Check @@evaled_dependencies again in case there was a dependency
217
+ # loop that already loaded this enum
218
+ return if @@evaled_dependencies.include?(name)
219
+ namespace = name.split(".")
220
+ eval_enum_code(enum, namespace[0..-2].join("."))
221
+ @@evaled_dependencies << name
222
+ else
223
+ fail "Error loading unknown dependencies, could not find message or enum #{name.inspect}"
224
+ end
225
+ end
226
+
227
+ def eval_message_code(fully_qualified_namespace, fields = [])
228
+ group = GroupGenerator.new(0)
229
+ group.add_extended_messages({ fully_qualified_namespace => fields }, false)
230
+ print group.to_s
231
+ eval_code
232
+ end
233
+
234
+ def eval_enum_code(enum, fully_qualified_namespace)
235
+ group = GroupGenerator.new(0)
236
+ group.add_enums([enum], :namespace => [fully_qualified_namespace])
237
+ print group.to_s
238
+ eval_code(modulize(fully_qualified_namespace).safe_constantize || Object)
239
+ end
240
+
241
+ def eval_code(context = Object)
242
+ warn "#{context.inspect}.module_eval #{print_contents.inspect}" if ENV['PB_DEBUG']
243
+ context.module_eval print_contents.to_s
244
+ @io.truncate(0)
245
+ @io.rewind
246
+ end
247
+
248
+ def create_ruby_namespace_heiarchy(namespace)
249
+ loop do
250
+ namespace, _match, _tail = namespace.rpartition(".")
251
+ break if namespace.empty?
252
+ eval_dependencies(namespace)
253
+ end
254
+ end
255
+
145
256
  def inject_optionable
146
257
  return if descriptor.package.empty? && !ENV.key?('PB_ALLOW_DEFAULT_PACKAGE_NAME')
147
258
  puts "::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }"
@@ -2,6 +2,7 @@ require 'protobuf/generators/enum_generator'
2
2
  require 'protobuf/generators/extension_generator'
3
3
  require 'protobuf/generators/field_generator'
4
4
  require 'protobuf/generators/message_generator'
5
+ require 'protobuf/generators/option_generator'
5
6
  require 'protobuf/generators/service_generator'
6
7
 
7
8
  module Protobuf
@@ -18,10 +19,14 @@ module Protobuf
18
19
  @comments = {}
19
20
  @handlers = {}
20
21
  @indent_level = indent_level
21
- @order = [:enum, :message_declaration, :message, :extended_message, :service]
22
+ @order = [:enum, :message_declaration, :options, :message, :extended_message, :service]
22
23
  init_printer(indent_level)
23
24
  end
24
25
 
26
+ def add_options(option_descriptor)
27
+ @groups[:options] << OptionGenerator.new(option_descriptor, indent_level)
28
+ end
29
+
25
30
  def add_enums(enum_descriptors, options)
26
31
  enum_descriptors.each do |enum_descriptor|
27
32
  @groups[:enum] << EnumGenerator.new(enum_descriptor, indent_level, options)
@@ -32,8 +37,9 @@ module Protobuf
32
37
  @comments[type] = message
33
38
  end
34
39
 
35
- def add_extended_messages(extended_messages)
40
+ def add_extended_messages(extended_messages, skip_empty_fields = true)
36
41
  extended_messages.each do |message_type, field_descriptors|
42
+ next if skip_empty_fields && field_descriptors.empty?
37
43
  @groups[:extended_message] << ExtensionGenerator.new(message_type, field_descriptors, indent_level)
38
44
  end
39
45
  end
@@ -98,7 +104,7 @@ module Protobuf
98
104
  end
99
105
  end
100
106
 
101
- puts if type == :message_declaration
107
+ puts if type == :message_declaration || type == :options
102
108
  end
103
109
  end
104
110
 
@@ -42,6 +42,8 @@ module Protobuf
42
42
  print_class(descriptor.name, nil) do
43
43
  group = GroupGenerator.new(current_indent)
44
44
  group.add_messages(descriptor.nested_type, :extension_fields => @extension_fields, :namespace => type_namespace)
45
+ group.add_comment(:options, 'Message Options')
46
+ group.add_options(descriptor.options) if options?
45
47
  group.add_message_fields(descriptor.field)
46
48
  self.class.validate_tags(fully_qualified_type_namespace, descriptor.field.map(&:number))
47
49
 
@@ -52,7 +54,7 @@ module Protobuf
52
54
 
53
55
  group.add_extension_fields(message_extension_fields)
54
56
 
55
- group.order = [:message, :field, :extension_range, :extension_field]
57
+ group.order = [:message, :options, :field, :extension_range, :extension_field]
56
58
  print group.to_s
57
59
  end
58
60
  end
@@ -69,6 +71,10 @@ module Protobuf
69
71
  descriptor.field.count > 0
70
72
  end
71
73
 
74
+ def options?
75
+ descriptor.options
76
+ end
77
+
72
78
  def nested_enums?
73
79
  descriptor.enum_type.count > 0
74
80
  end
@@ -85,7 +91,7 @@ module Protobuf
85
91
  if @only_declarations
86
92
  nested_types?
87
93
  else
88
- fields? || nested_messages? || extensions?
94
+ fields? || nested_messages? || extensions? || options?
89
95
  end
90
96
  end
91
97
 
@@ -0,0 +1,17 @@
1
+ require 'protobuf/generators/base'
2
+
3
+ module Protobuf
4
+ module Generators
5
+ class OptionGenerator < Base
6
+ def compile
7
+ run_once(:compile) do
8
+ descriptor.each_field.map do |field, value|
9
+ next unless descriptor.field?(field.name)
10
+ serialized_value = serialize_value(value)
11
+ puts "set_option #{field.fully_qualified_name.inspect}, #{serialized_value}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -93,14 +93,14 @@ module Protobuf
93
93
  # If a block is given, call the block from within an indent block.
94
94
  # Otherwise, end the block on the same line.
95
95
  #
96
- def print_block(name, parent_klass, type, &block)
96
+ def print_block(name, parent_klass, type)
97
97
  name = modulize(name)
98
98
  block_def = "#{type} #{name}"
99
99
  block_def += " < #{parent_class(parent_klass)}" if parent_klass
100
100
 
101
101
  if block_given?
102
102
  puts block_def
103
- indent { block.call }
103
+ indent { yield }
104
104
  puts "end"
105
105
  puts
106
106
  else
@@ -1,4 +1,5 @@
1
1
  require 'protobuf/generators/base'
2
+ require 'protobuf/generators/option_generator'
2
3
 
3
4
  module Protobuf
4
5
  module Generators
@@ -7,18 +8,41 @@ module Protobuf
7
8
  def compile
8
9
  run_once(:compile) do
9
10
  print_class(descriptor.name, :service) do
11
+ print OptionGenerator.new(descriptor.options, current_indent).to_s if descriptor.options
10
12
  descriptor.method.each do |method_descriptor|
11
- puts build_method(method_descriptor)
13
+ print_method(method_descriptor)
12
14
  end
13
15
  end
14
16
  end
15
17
  end
16
18
 
17
- def build_method(method_descriptor)
19
+ private
20
+
21
+ def print_method(method_descriptor)
18
22
  request_klass = modulize(method_descriptor.input_type)
19
23
  response_klass = modulize(method_descriptor.output_type)
20
24
  name = ENV.key?('PB_USE_RAW_RPC_NAMES') ? method_descriptor.name : method_descriptor.name.underscore
21
- "rpc :#{name}, #{request_klass}, #{response_klass}"
25
+ options = {}
26
+ if method_descriptor.options
27
+ method_descriptor.options.each_field do |field_option|
28
+ option_value = method_descriptor.options[field_option.name]
29
+ next unless method_descriptor.options.field?(field_option.name)
30
+ options[field_option.fully_qualified_name] = serialize_value(option_value)
31
+ end
32
+ end
33
+
34
+ rpc = "rpc :#{name}, #{request_klass}, #{response_klass}"
35
+
36
+ if options.empty?
37
+ puts rpc
38
+ return
39
+ end
40
+
41
+ puts rpc + " do"
42
+ options.each do |option_name, value|
43
+ indent { puts "set_option #{option_name.inspect}, #{value}" }
44
+ end
45
+ puts "end"
22
46
  end
23
47
 
24
48
  end
@@ -9,7 +9,7 @@ module Protobuf
9
9
  yield(*args)
10
10
  end
11
11
  end
12
- alias_method :on, :register
12
+ alias :on register
13
13
 
14
14
  def trigger(event_name, *args)
15
15
  event_name = normalized_event_name(event_name)
@@ -134,25 +134,23 @@ module Protobuf
134
134
  # message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]
135
135
  # message[:'.my_package.string_field'] #=> @values[".my_package.string_field"]
136
136
 
137
- if options[:extension]
138
- base_name = fully_qualified_field_name.to_s.split('.').last.to_sym
139
- if field_store[base_name]
140
- # Case 3
141
- if field_store[base_name].extension?
142
- remove_existing_accessors(base_name)
143
- simple_name = nil
144
- # Case 2
137
+ simple_name =
138
+ if options[:extension]
139
+ base_name = fully_qualified_field_name.to_s.split('.').last.to_sym
140
+ if field_store[base_name]
141
+ # Case 3
142
+ if field_store[base_name].extension?
143
+ remove_existing_accessors(base_name)
144
+ end
145
+ nil
146
+ # Case 4
145
147
  else
146
- simple_name = nil
148
+ base_name
147
149
  end
148
- # Case 4
149
150
  else
150
- simple_name = base_name
151
+ # Case 1
152
+ fully_qualified_field_name
151
153
  end
152
- else
153
- # Case 1
154
- simple_name = fully_qualified_field_name
155
- end
156
154
 
157
155
  field = ::Protobuf::Field.build(self, rule, type_class, fully_qualified_field_name,
158
156
  tag, simple_name, options)
@@ -63,15 +63,15 @@ module Protobuf
63
63
  ##
64
64
  # Instance Aliases
65
65
  #
66
- alias_method :parse_from_string, :decode
67
- alias_method :deserialize, :decode
68
- alias_method :parse_from, :decode_from
69
- alias_method :deserialize_from, :decode_from
70
- alias_method :to_s, :encode
71
- alias_method :bytes, :encode
72
- alias_method :serialize, :encode
73
- alias_method :serialize_to_string, :encode
74
- alias_method :serialize_to, :encode_to
66
+ alias :parse_from_string decode
67
+ alias :deserialize decode
68
+ alias :parse_from decode_from
69
+ alias :deserialize_from decode_from
70
+ alias :to_s encode
71
+ alias :bytes encode
72
+ alias :serialize encode
73
+ alias :serialize_to_string encode
74
+ alias :serialize_to encode_to
75
75
 
76
76
  private
77
77
 
@@ -150,17 +150,13 @@ module Protobuf
150
150
  end
151
151
 
152
152
  def [](name)
153
- if (field = self.class.get_field(name, true))
154
- if field.repeated?
155
- @values[field.fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(field)
156
- elsif @values.key?(field.fully_qualified_name)
157
- @values[field.fully_qualified_name]
158
- else
159
- field.default_value
160
- end
161
- else
162
- fail ArgumentError, "invalid field name=#{name.inspect}"
163
- end
153
+ field = self.class.get_field(name, true)
154
+ return @values[field.fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(field) if field.repeated?
155
+
156
+ @values.fetch(field.fully_qualified_name, field.default_value)
157
+ rescue # not having a field should be the exceptional state
158
+ raise if field
159
+ fail ArgumentError, "invalid field name=#{name.inspect}"
164
160
  end
165
161
 
166
162
  def []=(name, value)
@@ -170,17 +166,17 @@ module Protobuf
170
166
  ##
171
167
  # Instance Aliases
172
168
  #
173
- alias_method :to_hash_value, :to_hash
174
- alias_method :to_proto_hash, :to_hash
175
- alias_method :responds_to_has?, :respond_to_has?
176
- alias_method :respond_to_and_has?, :respond_to_has?
177
- alias_method :responds_to_and_has?, :respond_to_has?
178
- alias_method :respond_to_has_present?, :respond_to_has_and_present?
179
- alias_method :respond_to_and_has_present?, :respond_to_has_and_present?
180
- alias_method :respond_to_and_has_and_present?, :respond_to_has_and_present?
181
- alias_method :responds_to_has_present?, :respond_to_has_and_present?
182
- alias_method :responds_to_and_has_present?, :respond_to_has_and_present?
183
- alias_method :responds_to_and_has_and_present?, :respond_to_has_and_present?
169
+ alias :to_hash_value to_hash
170
+ alias :to_proto_hash to_hash
171
+ alias :responds_to_has? respond_to_has?
172
+ alias :respond_to_and_has? respond_to_has?
173
+ alias :responds_to_and_has? respond_to_has?
174
+ alias :respond_to_has_present? respond_to_has_and_present?
175
+ alias :respond_to_and_has_present? respond_to_has_and_present?
176
+ alias :respond_to_and_has_and_present? respond_to_has_and_present?
177
+ alias :responds_to_has_present? respond_to_has_and_present?
178
+ alias :responds_to_and_has_present? respond_to_has_and_present?
179
+ alias :responds_to_and_has_and_present? respond_to_has_and_present?
184
180
 
185
181
  ##
186
182
  # Private Instance Methods
@@ -195,15 +191,15 @@ module Protobuf
195
191
  ::Protobuf.deprecator.deprecation_warning("#{self.class}#[#{name}]=nil", "use an empty array instead of nil")
196
192
  return
197
193
  end
198
- if value.is_a?(Array)
199
- value = value.compact
200
- else
194
+ unless value.is_a?(Array)
201
195
  fail TypeError, <<-TYPE_ERROR
202
196
  Expected repeated value of type '#{field.type_class}'
203
197
  Got '#{value.class}' for repeated protobuf field #{field.name}
204
198
  TYPE_ERROR
205
199
  end
206
200
 
201
+ value = value.compact
202
+
207
203
  if value.empty?
208
204
  @values.delete(field.fully_qualified_name)
209
205
  else
@@ -211,12 +207,10 @@ module Protobuf
211
207
  @values[field.fully_qualified_name].replace(value)
212
208
  end
213
209
  else
214
- if value.nil?
210
+ if value.nil? # rubocop:disable Style/IfInsideElse
215
211
  @values.delete(field.fully_qualified_name)
216
- elsif field.acceptable?(value)
217
- @values[field.fully_qualified_name] = field.coerce!(value)
218
212
  else
219
- fail TypeError, "Unacceptable value #{value} for field #{field.name} of type #{field.type_class}"
213
+ @values[field.fully_qualified_name] = field.coerce!(value)
220
214
  end
221
215
  end
222
216
  else