protobuf-cucumber 3.10.4

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 (204) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rubocop.yml +70 -0
  4. data/.rubocop_todo.yml +145 -0
  5. data/.travis.yml +40 -0
  6. data/.yardopts +5 -0
  7. data/CHANGES.md +344 -0
  8. data/CONTRIBUTING.md +16 -0
  9. data/Gemfile +3 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +33 -0
  12. data/Rakefile +64 -0
  13. data/bin/protoc-gen-ruby +22 -0
  14. data/bin/rpc_server +5 -0
  15. data/install-protobuf.sh +28 -0
  16. data/lib/protobuf.rb +129 -0
  17. data/lib/protobuf/cli.rb +257 -0
  18. data/lib/protobuf/code_generator.rb +120 -0
  19. data/lib/protobuf/decoder.rb +28 -0
  20. data/lib/protobuf/deprecation.rb +117 -0
  21. data/lib/protobuf/descriptors.rb +3 -0
  22. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +62 -0
  23. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +301 -0
  24. data/lib/protobuf/encoder.rb +11 -0
  25. data/lib/protobuf/enum.rb +365 -0
  26. data/lib/protobuf/exceptions.rb +9 -0
  27. data/lib/protobuf/field.rb +74 -0
  28. data/lib/protobuf/field/base_field.rb +380 -0
  29. data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
  30. data/lib/protobuf/field/bool_field.rb +64 -0
  31. data/lib/protobuf/field/bytes_field.rb +78 -0
  32. data/lib/protobuf/field/double_field.rb +25 -0
  33. data/lib/protobuf/field/enum_field.rb +61 -0
  34. data/lib/protobuf/field/field_array.rb +104 -0
  35. data/lib/protobuf/field/field_hash.rb +122 -0
  36. data/lib/protobuf/field/fixed32_field.rb +25 -0
  37. data/lib/protobuf/field/fixed64_field.rb +28 -0
  38. data/lib/protobuf/field/float_field.rb +43 -0
  39. data/lib/protobuf/field/int32_field.rb +21 -0
  40. data/lib/protobuf/field/int64_field.rb +34 -0
  41. data/lib/protobuf/field/integer_field.rb +23 -0
  42. data/lib/protobuf/field/message_field.rb +51 -0
  43. data/lib/protobuf/field/sfixed32_field.rb +27 -0
  44. data/lib/protobuf/field/sfixed64_field.rb +28 -0
  45. data/lib/protobuf/field/signed_integer_field.rb +29 -0
  46. data/lib/protobuf/field/sint32_field.rb +21 -0
  47. data/lib/protobuf/field/sint64_field.rb +21 -0
  48. data/lib/protobuf/field/string_field.rb +51 -0
  49. data/lib/protobuf/field/uint32_field.rb +21 -0
  50. data/lib/protobuf/field/uint64_field.rb +21 -0
  51. data/lib/protobuf/field/varint_field.rb +77 -0
  52. data/lib/protobuf/generators/base.rb +85 -0
  53. data/lib/protobuf/generators/enum_generator.rb +39 -0
  54. data/lib/protobuf/generators/extension_generator.rb +27 -0
  55. data/lib/protobuf/generators/field_generator.rb +193 -0
  56. data/lib/protobuf/generators/file_generator.rb +262 -0
  57. data/lib/protobuf/generators/group_generator.rb +122 -0
  58. data/lib/protobuf/generators/message_generator.rb +104 -0
  59. data/lib/protobuf/generators/option_generator.rb +17 -0
  60. data/lib/protobuf/generators/printable.rb +160 -0
  61. data/lib/protobuf/generators/service_generator.rb +50 -0
  62. data/lib/protobuf/lifecycle.rb +33 -0
  63. data/lib/protobuf/logging.rb +39 -0
  64. data/lib/protobuf/message.rb +260 -0
  65. data/lib/protobuf/message/fields.rb +233 -0
  66. data/lib/protobuf/message/serialization.rb +85 -0
  67. data/lib/protobuf/optionable.rb +70 -0
  68. data/lib/protobuf/rpc/buffer.rb +78 -0
  69. data/lib/protobuf/rpc/client.rb +140 -0
  70. data/lib/protobuf/rpc/connectors/base.rb +221 -0
  71. data/lib/protobuf/rpc/connectors/ping.rb +89 -0
  72. data/lib/protobuf/rpc/connectors/socket.rb +78 -0
  73. data/lib/protobuf/rpc/connectors/zmq.rb +319 -0
  74. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +50 -0
  75. data/lib/protobuf/rpc/env.rb +60 -0
  76. data/lib/protobuf/rpc/error.rb +28 -0
  77. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  78. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  79. data/lib/protobuf/rpc/middleware.rb +25 -0
  80. data/lib/protobuf/rpc/middleware/exception_handler.rb +40 -0
  81. data/lib/protobuf/rpc/middleware/logger.rb +95 -0
  82. data/lib/protobuf/rpc/middleware/request_decoder.rb +79 -0
  83. data/lib/protobuf/rpc/middleware/response_encoder.rb +83 -0
  84. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  85. data/lib/protobuf/rpc/rpc.pb.rb +64 -0
  86. data/lib/protobuf/rpc/rpc_method.rb +16 -0
  87. data/lib/protobuf/rpc/server.rb +39 -0
  88. data/lib/protobuf/rpc/servers/socket/server.rb +121 -0
  89. data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
  90. data/lib/protobuf/rpc/servers/socket_runner.rb +46 -0
  91. data/lib/protobuf/rpc/servers/zmq/broker.rb +194 -0
  92. data/lib/protobuf/rpc/servers/zmq/server.rb +321 -0
  93. data/lib/protobuf/rpc/servers/zmq/util.rb +48 -0
  94. data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
  95. data/lib/protobuf/rpc/servers/zmq_runner.rb +70 -0
  96. data/lib/protobuf/rpc/service.rb +172 -0
  97. data/lib/protobuf/rpc/service_directory.rb +261 -0
  98. data/lib/protobuf/rpc/service_dispatcher.rb +45 -0
  99. data/lib/protobuf/rpc/service_filters.rb +250 -0
  100. data/lib/protobuf/rpc/stat.rb +119 -0
  101. data/lib/protobuf/socket.rb +21 -0
  102. data/lib/protobuf/tasks.rb +1 -0
  103. data/lib/protobuf/tasks/compile.rake +80 -0
  104. data/lib/protobuf/varint.rb +20 -0
  105. data/lib/protobuf/varint_pure.rb +31 -0
  106. data/lib/protobuf/version.rb +3 -0
  107. data/lib/protobuf/wire_type.rb +10 -0
  108. data/lib/protobuf/zmq.rb +21 -0
  109. data/profile.html +5103 -0
  110. data/proto/dynamic_discovery.proto +44 -0
  111. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  112. data/proto/google/protobuf/descriptor.proto +779 -0
  113. data/proto/rpc.proto +69 -0
  114. data/protobuf-cucumber.gemspec +57 -0
  115. data/spec/benchmark/tasks.rb +143 -0
  116. data/spec/bin/protoc-gen-ruby_spec.rb +23 -0
  117. data/spec/encoding/all_types_spec.rb +103 -0
  118. data/spec/encoding/extreme_values_spec.rb +0 -0
  119. data/spec/functional/class_inheritance_spec.rb +52 -0
  120. data/spec/functional/code_generator_spec.rb +58 -0
  121. data/spec/functional/socket_server_spec.rb +59 -0
  122. data/spec/functional/zmq_server_spec.rb +105 -0
  123. data/spec/lib/protobuf/cli_spec.rb +317 -0
  124. data/spec/lib/protobuf/code_generator_spec.rb +87 -0
  125. data/spec/lib/protobuf/enum_spec.rb +307 -0
  126. data/spec/lib/protobuf/field/bool_field_spec.rb +91 -0
  127. data/spec/lib/protobuf/field/double_field_spec.rb +9 -0
  128. data/spec/lib/protobuf/field/enum_field_spec.rb +44 -0
  129. data/spec/lib/protobuf/field/field_array_spec.rb +105 -0
  130. data/spec/lib/protobuf/field/field_hash_spec.rb +168 -0
  131. data/spec/lib/protobuf/field/fixed32_field_spec.rb +7 -0
  132. data/spec/lib/protobuf/field/fixed64_field_spec.rb +7 -0
  133. data/spec/lib/protobuf/field/float_field_spec.rb +90 -0
  134. data/spec/lib/protobuf/field/int32_field_spec.rb +120 -0
  135. data/spec/lib/protobuf/field/int64_field_spec.rb +7 -0
  136. data/spec/lib/protobuf/field/message_field_spec.rb +132 -0
  137. data/spec/lib/protobuf/field/sfixed32_field_spec.rb +9 -0
  138. data/spec/lib/protobuf/field/sfixed64_field_spec.rb +9 -0
  139. data/spec/lib/protobuf/field/sint32_field_spec.rb +9 -0
  140. data/spec/lib/protobuf/field/sint64_field_spec.rb +9 -0
  141. data/spec/lib/protobuf/field/string_field_spec.rb +79 -0
  142. data/spec/lib/protobuf/field/uint32_field_spec.rb +7 -0
  143. data/spec/lib/protobuf/field/uint64_field_spec.rb +7 -0
  144. data/spec/lib/protobuf/field_spec.rb +192 -0
  145. data/spec/lib/protobuf/generators/base_spec.rb +154 -0
  146. data/spec/lib/protobuf/generators/enum_generator_spec.rb +82 -0
  147. data/spec/lib/protobuf/generators/extension_generator_spec.rb +42 -0
  148. data/spec/lib/protobuf/generators/field_generator_spec.rb +197 -0
  149. data/spec/lib/protobuf/generators/file_generator_spec.rb +119 -0
  150. data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
  151. data/spec/lib/protobuf/generators/service_generator_spec.rb +99 -0
  152. data/spec/lib/protobuf/lifecycle_spec.rb +94 -0
  153. data/spec/lib/protobuf/message_spec.rb +944 -0
  154. data/spec/lib/protobuf/optionable_spec.rb +265 -0
  155. data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
  156. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +226 -0
  157. data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +69 -0
  158. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +34 -0
  159. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +110 -0
  160. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  161. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  162. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  163. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +91 -0
  164. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
  165. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +43 -0
  166. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
  167. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
  168. data/spec/lib/protobuf/rpc/service_directory_spec.rb +293 -0
  169. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +35 -0
  170. data/spec/lib/protobuf/rpc/service_filters_spec.rb +517 -0
  171. data/spec/lib/protobuf/rpc/service_spec.rb +162 -0
  172. data/spec/lib/protobuf/rpc/stat_spec.rb +101 -0
  173. data/spec/lib/protobuf/varint_spec.rb +29 -0
  174. data/spec/lib/protobuf_spec.rb +105 -0
  175. data/spec/spec_helper.rb +42 -0
  176. data/spec/support/all.rb +6 -0
  177. data/spec/support/packed_field.rb +23 -0
  178. data/spec/support/protos/all_types.data.bin +0 -0
  179. data/spec/support/protos/all_types.data.txt +119 -0
  180. data/spec/support/protos/enum.pb.rb +63 -0
  181. data/spec/support/protos/enum.proto +37 -0
  182. data/spec/support/protos/extreme_values.data.bin +0 -0
  183. data/spec/support/protos/google_unittest.bin +0 -0
  184. data/spec/support/protos/google_unittest.pb.rb +798 -0
  185. data/spec/support/protos/google_unittest.proto +884 -0
  186. data/spec/support/protos/google_unittest_custom_options.bin +0 -0
  187. data/spec/support/protos/google_unittest_custom_options.pb.rb +361 -0
  188. data/spec/support/protos/google_unittest_custom_options.proto +424 -0
  189. data/spec/support/protos/google_unittest_import.pb.rb +55 -0
  190. data/spec/support/protos/google_unittest_import.proto +73 -0
  191. data/spec/support/protos/google_unittest_import_public.pb.rb +31 -0
  192. data/spec/support/protos/google_unittest_import_public.proto +41 -0
  193. data/spec/support/protos/map-test.bin +157 -0
  194. data/spec/support/protos/map-test.pb.rb +85 -0
  195. data/spec/support/protos/map-test.proto +68 -0
  196. data/spec/support/protos/multi_field_extensions.pb.rb +59 -0
  197. data/spec/support/protos/multi_field_extensions.proto +35 -0
  198. data/spec/support/protos/resource.pb.rb +172 -0
  199. data/spec/support/protos/resource.proto +137 -0
  200. data/spec/support/resource_service.rb +23 -0
  201. data/spec/support/server.rb +65 -0
  202. data/spec/support/test_app_file.rb +2 -0
  203. data/varint_prof.rb +82 -0
  204. metadata +579 -0
@@ -0,0 +1,64 @@
1
+ require 'protobuf/field/varint_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class BoolField < VarintField
6
+ ONE = 1
7
+ FALSE_ENCODE = [0].pack('C')
8
+ FALSE_STRING = "false".freeze
9
+ FALSE_VALUES = [false, FALSE_STRING].freeze
10
+ TRUE_ENCODE = [1].pack('C')
11
+ TRUE_STRING = "true".freeze
12
+ TRUE_VALUES = [true, TRUE_STRING].freeze
13
+ ACCEPTABLES = [true, false, TRUE_STRING, FALSE_STRING].freeze
14
+
15
+ ##
16
+ # Class Methods
17
+ #
18
+
19
+ def self.default
20
+ false
21
+ end
22
+
23
+ ##
24
+ # Public Instance Methods
25
+ # #
26
+
27
+ def acceptable?(val)
28
+ ACCEPTABLES.include?(val)
29
+ end
30
+
31
+ def coerce!(val)
32
+ if TRUE_VALUES.include?(val)
33
+ true
34
+ elsif FALSE_VALUES.include?(val)
35
+ false
36
+ else
37
+ fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'"
38
+ end
39
+ end
40
+
41
+ def decode(value)
42
+ value == ONE
43
+ end
44
+
45
+ def encode(value)
46
+ value ? TRUE_ENCODE : FALSE_ENCODE
47
+ end
48
+
49
+ private
50
+
51
+ ##
52
+ # Private Instance Methods
53
+ #
54
+
55
+ def define_accessor(simple_field_name, _fully_qualified_field_name)
56
+ super
57
+ message_class.class_eval do
58
+ alias_method "#{simple_field_name}?", simple_field_name
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,78 @@
1
+ require 'protobuf/wire_type'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class BytesField < BaseField
6
+
7
+ ##
8
+ # Constants
9
+ #
10
+
11
+ BYTES_ENCODING = Encoding::BINARY
12
+
13
+ ##
14
+ # Class Methods
15
+ #
16
+
17
+ def self.default
18
+ ''
19
+ end
20
+
21
+ ##
22
+ # Public Instance Methods
23
+ #
24
+
25
+ def acceptable?(val)
26
+ val.is_a?(String) || val.nil? || val.is_a?(Symbol) || val.is_a?(::Protobuf::Message)
27
+ end
28
+
29
+ def decode(bytes)
30
+ bytes.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
31
+ bytes
32
+ end
33
+
34
+ def encode(value)
35
+ value_to_encode = if value.is_a?(::Protobuf::Message)
36
+ value.encode
37
+ else
38
+ "" + value
39
+ end
40
+
41
+ value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
42
+ "#{::Protobuf::Field::VarintField.encode(value_to_encode.bytesize)}#{value_to_encode}"
43
+ end
44
+
45
+ def wire_type
46
+ ::Protobuf::WireType::LENGTH_DELIMITED
47
+ end
48
+
49
+ def coerce!(value)
50
+ case value
51
+ when String
52
+ if value.encoding == Encoding::ASCII_8BIT
53
+ # This is a "binary" string
54
+ value
55
+ else
56
+ # Assume the value is Base64 encoded (from JSON)
57
+ # Ideally we'd do the Base64 decoding while processing the JSON,
58
+ # but this is tricky to do since we don't know the protobuf field
59
+ # types when we do that.
60
+ Base64.decode64(value)
61
+ end
62
+ when Symbol
63
+ value.to_s
64
+ when NilClass
65
+ nil
66
+ when ::Protobuf::Message
67
+ value.dup
68
+ else
69
+ fail TypeError, "Unacceptable value #{value} for field #{name} of type #{type_class}"
70
+ end
71
+ end
72
+
73
+ def json_encode(value)
74
+ Base64.strict_encode64(value)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,25 @@
1
+ require 'protobuf/field/float_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class DoubleField < FloatField
6
+
7
+ ##
8
+ # Public Instance Methods
9
+ #
10
+
11
+ def decode(bytes)
12
+ bytes.unpack('E').first
13
+ end
14
+
15
+ def encode(value)
16
+ [value].pack('E')
17
+ end
18
+
19
+ def wire_type
20
+ WireType::FIXED64
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ require 'protobuf/field/integer_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class EnumField < IntegerField
6
+
7
+ ##
8
+ # Class Methods
9
+ #
10
+
11
+ def self.default
12
+ fail NoMethodError, "#{self}.#{__method__} must be called on an instance"
13
+ end
14
+
15
+ ##
16
+ # Public Instance Methods
17
+ #
18
+ def encode(value)
19
+ # original Google's library uses 64bits integer for negative value
20
+ ::Protobuf::Field::VarintField.encode(value.to_i & 0xffff_ffff_ffff_ffff)
21
+ end
22
+
23
+ def decode(value)
24
+ value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero?
25
+ value if acceptable?(value)
26
+ end
27
+
28
+ def acceptable?(val)
29
+ !type_class.fetch(val).nil?
30
+ end
31
+
32
+ def enum?
33
+ true
34
+ end
35
+
36
+ def coerce!(value)
37
+ type_class.fetch(value) || fail(TypeError, "Invalid Enum value: #{value.inspect} for #{name}")
38
+ end
39
+
40
+ def json_encode(value)
41
+ enum = type_class.enums.find { |e| e.to_i == value }
42
+ enum.to_s(:name)
43
+ end
44
+
45
+ private
46
+
47
+ ##
48
+ # Private Instance Methods
49
+ #
50
+
51
+ def typed_default_value
52
+ if default.is_a?(Symbol)
53
+ type_class.const_get(default)
54
+ else
55
+ type_class.fetch(default) || type_class.enums.first
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,104 @@
1
+ module Protobuf
2
+ module Field
3
+ class FieldArray < Array
4
+
5
+ ##
6
+ # Attributes
7
+ #
8
+
9
+ attr_reader :field
10
+
11
+ ##
12
+ # Constructor
13
+ #
14
+
15
+ def initialize(field)
16
+ @field = field
17
+ end
18
+
19
+ ##
20
+ # Public Instance Methods
21
+ #
22
+
23
+ def []=(nth, val)
24
+ super(nth, normalize(val)) unless val.nil?
25
+ end
26
+
27
+ def <<(val)
28
+ super(normalize(val)) unless val.nil?
29
+ end
30
+
31
+ def push(val)
32
+ super(normalize(val)) unless val.nil?
33
+ end
34
+
35
+ def replace(val)
36
+ raise_type_error(val) unless val.is_a?(Array)
37
+ val.map! { |v| normalize(v) }
38
+ super(val)
39
+ end
40
+
41
+ # Return a hash-representation of the given values for this field type.
42
+ # The value in this case would be an array.
43
+ def to_hash_value
44
+ map do |value|
45
+ value.respond_to?(:to_hash_value) ? value.to_hash_value : value
46
+ end
47
+ end
48
+
49
+ # Return a hash-representation of the given values for this field type
50
+ # that is safe to convert to JSON.
51
+ # The value in this case would be an array.
52
+ def to_json_hash_value(options = {})
53
+ if field.respond_to?(:json_encode)
54
+ map do |value|
55
+ field.json_encode(value)
56
+ end
57
+ else
58
+ map do |value|
59
+ value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value(options) : value
60
+ end
61
+ end
62
+ end
63
+
64
+ def to_s
65
+ "[#{field.name}]"
66
+ end
67
+
68
+ def unshift(val)
69
+ super(normalize(val)) unless val.nil?
70
+ end
71
+
72
+ private
73
+
74
+ ##
75
+ # Private Instance Methods
76
+ #
77
+
78
+ def normalize(value)
79
+ value = value.to_proto if value.respond_to?(:to_proto)
80
+ fail TypeError, "Unacceptable value #{value} for field #{field.name} of type #{field.type_class}" unless field.acceptable?(value)
81
+
82
+ if field.is_a?(::Protobuf::Field::EnumField)
83
+ field.type_class.fetch(value)
84
+ elsif field.is_a?(::Protobuf::Field::BytesField)
85
+ field.coerce!(value)
86
+ elsif field.is_a?(::Protobuf::Field::MessageField) && value.is_a?(field.type_class)
87
+ value
88
+ elsif field.is_a?(::Protobuf::Field::MessageField) && value.respond_to?(:to_hash)
89
+ field.type_class.new(value.to_hash)
90
+ else
91
+ value
92
+ end
93
+ end
94
+
95
+ def raise_type_error(val)
96
+ fail TypeError, <<-TYPE_ERROR
97
+ Expected repeated value of type '#{field.type_class}'
98
+ Got '#{val.class}' for repeated protobuf field #{field.name}
99
+ TYPE_ERROR
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,122 @@
1
+ module Protobuf
2
+ module Field
3
+ class FieldHash < Hash
4
+
5
+ ##
6
+ # Attributes
7
+ #
8
+
9
+ attr_reader :field, :key_field, :value_field
10
+
11
+ ##
12
+ # Constructor
13
+ #
14
+
15
+ def initialize(field)
16
+ @field = field
17
+ @key_field = field.type_class.get_field(:key)
18
+ @value_field = field.type_class.get_field(:value)
19
+ end
20
+
21
+ ##
22
+ # Public Instance Methods
23
+ #
24
+
25
+ def []=(key, val)
26
+ super(normalize_key(key), normalize_val(val))
27
+ end
28
+
29
+ alias store []=
30
+
31
+ def replace(val)
32
+ raise_type_error(val) unless val.is_a?(Hash)
33
+ clear
34
+ update(val)
35
+ end
36
+
37
+ def merge!(other)
38
+ raise_type_error(other) unless other.is_a?(Hash)
39
+ # keys and values will be normalized by []= above
40
+ other.each { |k, v| self[k] = v }
41
+ end
42
+
43
+ alias update merge!
44
+
45
+ # Return a hash-representation of the given values for this field type.
46
+ # The value in this case would be the hash itself, right? Unfortunately
47
+ # not because the values of the map could be messages themselves that we
48
+ # need to transform.
49
+ def to_hash_value
50
+ each_with_object({}) do |(key, value), hash|
51
+ hash[key] = value.respond_to?(:to_hash_value) ? value.to_hash_value : value
52
+ end
53
+ end
54
+
55
+ # Return a hash-representation of the given values for this field type
56
+ # that is safe to convert to JSON.
57
+ #
58
+ # The value in this case would be the hash itself, right? Unfortunately
59
+ # not because the values of the map could be messages themselves that we
60
+ # need to transform.
61
+ def to_json_hash_value(options = {})
62
+ if field.respond_to?(:json_encode)
63
+ each_with_object({}) do |(key, value), hash|
64
+ hash[key] = field.json_encode(value)
65
+ end
66
+ else
67
+ each_with_object({}) do |(key, value), hash|
68
+ hash[key] = value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value(options) : value
69
+ end
70
+ end
71
+ end
72
+
73
+ def to_s
74
+ "{#{field.name}}"
75
+ end
76
+
77
+ private
78
+
79
+ ##
80
+ # Private Instance Methods
81
+ #
82
+
83
+ def normalize_key(key)
84
+ normalize(:key, key, key_field)
85
+ end
86
+
87
+ def normalize_val(value)
88
+ normalize(:value, value, value_field)
89
+ end
90
+
91
+ def normalize(what, value, normalize_field)
92
+ raise_type_error(value) if value.nil?
93
+ value = value.to_proto if value.respond_to?(:to_proto)
94
+ fail TypeError, "Unacceptable #{what} #{value} for field #{field.name} of type #{normalize_field.type_class}" unless normalize_field.acceptable?(value)
95
+
96
+ if normalize_field.is_a?(::Protobuf::Field::EnumField)
97
+ fetch_enum(normalize_field.type_class, value)
98
+ elsif normalize_field.is_a?(::Protobuf::Field::MessageField) && value.is_a?(normalize_field.type_class)
99
+ value
100
+ elsif normalize_field.is_a?(::Protobuf::Field::MessageField) && value.respond_to?(:to_hash)
101
+ normalize_field.type_class.new(value.to_hash)
102
+ else
103
+ value
104
+ end
105
+ end
106
+
107
+ def fetch_enum(type, val)
108
+ en = type.fetch(val)
109
+ raise_type_error(val) if en.nil?
110
+ en
111
+ end
112
+
113
+ def raise_type_error(val)
114
+ fail TypeError, <<-TYPE_ERROR
115
+ Expected map value of type '#{key_field.type_class} -> #{value_field.type_class}'
116
+ Got '#{val.class}' for map protobuf field #{field.name}
117
+ TYPE_ERROR
118
+ end
119
+
120
+ end
121
+ end
122
+ end