protobuffy 3.1.0

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 (192) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +5 -0
  5. data/CHANGES.md +261 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +14 -0
  9. data/README.md +58 -0
  10. data/Rakefile +61 -0
  11. data/bin/protoc-gen-ruby +17 -0
  12. data/bin/rpc_server +4 -0
  13. data/examples/bin/reverse-client-http +4 -0
  14. data/examples/bin/reverse-client-socket +4 -0
  15. data/examples/bin/reverse-client-zmq +4 -0
  16. data/examples/config.ru +6 -0
  17. data/examples/definitions/example/reverse.proto +12 -0
  18. data/examples/lib/example/reverse-client.rb +23 -0
  19. data/examples/lib/example/reverse-service.rb +9 -0
  20. data/examples/lib/example/reverse.pb.rb +36 -0
  21. data/lib/protobuf.rb +106 -0
  22. data/lib/protobuf/cli.rb +249 -0
  23. data/lib/protobuf/code_generator.rb +41 -0
  24. data/lib/protobuf/decoder.rb +74 -0
  25. data/lib/protobuf/deprecator.rb +42 -0
  26. data/lib/protobuf/descriptors.rb +3 -0
  27. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
  28. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
  29. data/lib/protobuf/encoder.rb +62 -0
  30. data/lib/protobuf/enum.rb +319 -0
  31. data/lib/protobuf/exceptions.rb +9 -0
  32. data/lib/protobuf/field.rb +74 -0
  33. data/lib/protobuf/field/base_field.rb +280 -0
  34. data/lib/protobuf/field/bool_field.rb +53 -0
  35. data/lib/protobuf/field/bytes_field.rb +81 -0
  36. data/lib/protobuf/field/double_field.rb +26 -0
  37. data/lib/protobuf/field/enum_field.rb +57 -0
  38. data/lib/protobuf/field/field_array.rb +86 -0
  39. data/lib/protobuf/field/fixed32_field.rb +25 -0
  40. data/lib/protobuf/field/fixed64_field.rb +29 -0
  41. data/lib/protobuf/field/float_field.rb +38 -0
  42. data/lib/protobuf/field/int32_field.rb +22 -0
  43. data/lib/protobuf/field/int64_field.rb +22 -0
  44. data/lib/protobuf/field/integer_field.rb +24 -0
  45. data/lib/protobuf/field/message_field.rb +66 -0
  46. data/lib/protobuf/field/sfixed32_field.rb +28 -0
  47. data/lib/protobuf/field/sfixed64_field.rb +29 -0
  48. data/lib/protobuf/field/signed_integer_field.rb +30 -0
  49. data/lib/protobuf/field/sint32_field.rb +22 -0
  50. data/lib/protobuf/field/sint64_field.rb +22 -0
  51. data/lib/protobuf/field/string_field.rb +35 -0
  52. data/lib/protobuf/field/uint32_field.rb +22 -0
  53. data/lib/protobuf/field/uint64_field.rb +22 -0
  54. data/lib/protobuf/field/varint_field.rb +68 -0
  55. data/lib/protobuf/generators/base.rb +71 -0
  56. data/lib/protobuf/generators/enum_generator.rb +42 -0
  57. data/lib/protobuf/generators/extension_generator.rb +28 -0
  58. data/lib/protobuf/generators/field_generator.rb +132 -0
  59. data/lib/protobuf/generators/file_generator.rb +140 -0
  60. data/lib/protobuf/generators/group_generator.rb +113 -0
  61. data/lib/protobuf/generators/message_generator.rb +99 -0
  62. data/lib/protobuf/generators/printable.rb +161 -0
  63. data/lib/protobuf/generators/service_generator.rb +27 -0
  64. data/lib/protobuf/http.rb +20 -0
  65. data/lib/protobuf/lifecycle.rb +46 -0
  66. data/lib/protobuf/logger.rb +86 -0
  67. data/lib/protobuf/message.rb +182 -0
  68. data/lib/protobuf/message/fields.rb +122 -0
  69. data/lib/protobuf/message/serialization.rb +84 -0
  70. data/lib/protobuf/optionable.rb +23 -0
  71. data/lib/protobuf/rpc/buffer.rb +79 -0
  72. data/lib/protobuf/rpc/client.rb +168 -0
  73. data/lib/protobuf/rpc/connector.rb +21 -0
  74. data/lib/protobuf/rpc/connectors/base.rb +54 -0
  75. data/lib/protobuf/rpc/connectors/common.rb +172 -0
  76. data/lib/protobuf/rpc/connectors/http.rb +90 -0
  77. data/lib/protobuf/rpc/connectors/socket.rb +73 -0
  78. data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
  79. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
  80. data/lib/protobuf/rpc/env.rb +58 -0
  81. data/lib/protobuf/rpc/error.rb +28 -0
  82. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  83. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  84. data/lib/protobuf/rpc/middleware.rb +25 -0
  85. data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
  86. data/lib/protobuf/rpc/middleware/logger.rb +91 -0
  87. data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
  88. data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
  89. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  90. data/lib/protobuf/rpc/rpc.pb.rb +53 -0
  91. data/lib/protobuf/rpc/server.rb +39 -0
  92. data/lib/protobuf/rpc/servers/http/server.rb +101 -0
  93. data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
  94. data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
  95. data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
  96. data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
  97. data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
  98. data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
  99. data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
  100. data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
  101. data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
  102. data/lib/protobuf/rpc/service.rb +179 -0
  103. data/lib/protobuf/rpc/service_directory.rb +245 -0
  104. data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
  105. data/lib/protobuf/rpc/service_filters.rb +273 -0
  106. data/lib/protobuf/rpc/stat.rb +148 -0
  107. data/lib/protobuf/socket.rb +22 -0
  108. data/lib/protobuf/tasks.rb +1 -0
  109. data/lib/protobuf/tasks/compile.rake +61 -0
  110. data/lib/protobuf/version.rb +3 -0
  111. data/lib/protobuf/wire_type.rb +10 -0
  112. data/lib/protobuf/zmq.rb +21 -0
  113. data/proto/dynamic_discovery.proto +44 -0
  114. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  115. data/proto/google/protobuf/descriptor.proto +620 -0
  116. data/proto/rpc.proto +62 -0
  117. data/protobuffy.gemspec +37 -0
  118. data/spec/benchmark/tasks.rb +113 -0
  119. data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
  120. data/spec/data/data.bin +3 -0
  121. data/spec/data/types.bin +0 -0
  122. data/spec/encoding/all_types_spec.rb +91 -0
  123. data/spec/encoding/extreme_values_spec.rb +0 -0
  124. data/spec/functional/socket_server_spec.rb +59 -0
  125. data/spec/functional/zmq_server_spec.rb +103 -0
  126. data/spec/lib/protobuf/cli_spec.rb +267 -0
  127. data/spec/lib/protobuf/code_generator_spec.rb +60 -0
  128. data/spec/lib/protobuf/enum_spec.rb +239 -0
  129. data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
  130. data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
  131. data/spec/lib/protobuf/field_spec.rb +194 -0
  132. data/spec/lib/protobuf/generators/base_spec.rb +87 -0
  133. data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
  134. data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
  135. data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
  136. data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
  137. data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
  138. data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
  139. data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
  140. data/spec/lib/protobuf/logger_spec.rb +136 -0
  141. data/spec/lib/protobuf/message_spec.rb +368 -0
  142. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  143. data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
  144. data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
  145. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
  146. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
  147. data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
  148. data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
  149. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
  150. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
  151. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  152. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  153. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  154. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
  155. data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
  156. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
  157. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
  158. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
  159. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
  160. data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
  161. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
  162. data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
  163. data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
  164. data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
  165. data/spec/lib/protobuf_spec.rb +78 -0
  166. data/spec/spec_helper.rb +57 -0
  167. data/spec/support/all.rb +7 -0
  168. data/spec/support/packed_field.rb +22 -0
  169. data/spec/support/server.rb +94 -0
  170. data/spec/support/test/all_types.data.bin +0 -0
  171. data/spec/support/test/all_types.data.txt +119 -0
  172. data/spec/support/test/defaults.pb.rb +25 -0
  173. data/spec/support/test/defaults.proto +9 -0
  174. data/spec/support/test/enum.pb.rb +59 -0
  175. data/spec/support/test/enum.proto +34 -0
  176. data/spec/support/test/extended.pb.rb +22 -0
  177. data/spec/support/test/extended.proto +10 -0
  178. data/spec/support/test/extreme_values.data.bin +0 -0
  179. data/spec/support/test/google_unittest.pb.rb +543 -0
  180. data/spec/support/test/google_unittest.proto +713 -0
  181. data/spec/support/test/google_unittest_import.pb.rb +37 -0
  182. data/spec/support/test/google_unittest_import.proto +64 -0
  183. data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
  184. data/spec/support/test/google_unittest_import_public.proto +38 -0
  185. data/spec/support/test/multi_field_extensions.pb.rb +56 -0
  186. data/spec/support/test/multi_field_extensions.proto +33 -0
  187. data/spec/support/test/resource.pb.rb +117 -0
  188. data/spec/support/test/resource.proto +94 -0
  189. data/spec/support/test/resource_service.rb +26 -0
  190. data/spec/support/test_app_file.rb +2 -0
  191. data/spec/support/tolerance_matcher.rb +40 -0
  192. metadata +367 -0
@@ -0,0 +1,35 @@
1
+ require 'protobuf/field/bytes_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class StringField < BytesField
6
+
7
+ ##
8
+ # Constants
9
+ #
10
+
11
+ ENCODING = 'UTF-8'.freeze
12
+
13
+ ##
14
+ # Public Instance Methods
15
+ #
16
+
17
+ def decode(bytes)
18
+ bytes_to_decode = bytes.dup
19
+ bytes_to_decode.force_encoding(::Protobuf::Field::StringField::ENCODING)
20
+ bytes_to_decode
21
+ end
22
+
23
+ def encode(value)
24
+ value_to_encode = value.dup
25
+ value_to_encode.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "")
26
+ value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
27
+
28
+ string_size = ::Protobuf::Field::VarintField.encode(value_to_encode.size)
29
+ string_size << value_to_encode
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,22 @@
1
+ require 'protobuf/field/varint_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class Uint32Field < VarintField
6
+
7
+ ##
8
+ # Class Methods
9
+ #
10
+
11
+ def self.max
12
+ UINT32_MAX
13
+ end
14
+
15
+ def self.min
16
+ 0
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,22 @@
1
+ require 'protobuf/field/varint_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class Uint64Field < VarintField
6
+
7
+ ##
8
+ # Class Methods
9
+ #
10
+
11
+ def self.max
12
+ UINT64_MAX
13
+ end
14
+
15
+ def self.min
16
+ 0
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,68 @@
1
+ require 'protobuf/field/base_field'
2
+
3
+ module Protobuf
4
+ module Field
5
+ class VarintField < BaseField
6
+
7
+ ##
8
+ # Constants
9
+ #
10
+
11
+ INT32_MAX = 2**31 - 1
12
+ INT32_MIN = -2**31
13
+ INT64_MAX = 2**63 - 1
14
+ INT64_MIN = -2**63
15
+ UINT32_MAX = 2**32 - 1
16
+ UINT64_MAX = 2**64 - 1
17
+
18
+ ##
19
+ # Class Methods
20
+ #
21
+
22
+ def self.default
23
+ 0
24
+ end
25
+
26
+ def self.encode(value)
27
+ bytes = []
28
+ until value < 128
29
+ bytes << (0x80 | (value & 0x7f))
30
+ value >>= 7
31
+ end
32
+ (bytes << value).pack('C*')
33
+ end
34
+
35
+ ##
36
+ # Public Instance Methods
37
+ #
38
+
39
+ def acceptable?(val)
40
+ (val > self.class.min || val < self.class.max)
41
+ rescue
42
+ false
43
+ end
44
+
45
+ def decode(value)
46
+ value
47
+ end
48
+
49
+ def encode(value)
50
+ return [value].pack('C') if value < 128
51
+
52
+ bytes = []
53
+ until value == 0
54
+ bytes << (0x80 | (value & 0x7f))
55
+ value >>= 7
56
+ end
57
+ bytes[-1] &= 0x7f
58
+ bytes.pack('C*')
59
+ end
60
+
61
+ def wire_type
62
+ ::Protobuf::WireType::VARINT
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,71 @@
1
+ require 'protobuf/generators/printable'
2
+
3
+ module Protobuf
4
+ module Generators
5
+ class Base
6
+ include ::Protobuf::Generators::Printable
7
+
8
+ def self.validate_tags(type_name, tags)
9
+ return if tags.empty?
10
+
11
+ unique_tags = tags.uniq
12
+
13
+ if unique_tags.size < tags.size
14
+ ::Protobuf::CodeGenerator.fatal("#{type_name} object has duplicate tags. Expected #{unique_tags.size} tags, but got #{tags.size}. Suppress with PB_NO_TAG_WARNINGS=1.")
15
+ end
16
+
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
+
25
+ if tags.size < expected_size
26
+ ::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.")
28
+ end
29
+ end
30
+ end
31
+
32
+ attr_reader :descriptor, :namespace, :options
33
+
34
+ def initialize(descriptor, indent_level = 0, options = {})
35
+ @descriptor = descriptor
36
+ @options = options
37
+ @namespace = @options.fetch(:namespace) { [] }
38
+ init_printer(indent_level)
39
+ end
40
+
41
+ def fully_qualified_type_namespace
42
+ ".#{type_namespace.join('.')}"
43
+ end
44
+
45
+ def run_once(label, &block)
46
+ tracker_ivar = "@_#{label}_compiled"
47
+ value_ivar = "@_#{label}_compiled_value"
48
+
49
+ if instance_variable_get(tracker_ivar)
50
+ 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
+ end
57
+ end
58
+
59
+ def to_s
60
+ compile
61
+ print_contents # see Printable
62
+ end
63
+
64
+ def type_namespace
65
+ @type_namespace ||= @namespace + [ descriptor.name ]
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,42 @@
1
+ require 'protobuf/generators/base'
2
+
3
+ module Protobuf
4
+ module Generators
5
+ class EnumGenerator < Base
6
+
7
+ def allow_alias?
8
+ descriptor.options.try(:allow_alias!) { false }
9
+ end
10
+
11
+ def compile
12
+ run_once(:compile) do
13
+ tags = []
14
+
15
+ print_class(descriptor.name, :enum) do
16
+ if allow_alias?
17
+ puts "set_option :allow_alias"
18
+ puts
19
+ end
20
+
21
+ descriptor.value.each do |enum_value_descriptor|
22
+ tags << enum_value_descriptor.number
23
+ puts build_value(enum_value_descriptor)
24
+ end
25
+ end
26
+
27
+ unless allow_alias?
28
+ self.class.validate_tags(fully_qualified_type_namespace, tags)
29
+ end
30
+ end
31
+ end
32
+
33
+ def build_value(enum_value_descriptor)
34
+ name = enum_value_descriptor.name
35
+ number = enum_value_descriptor.number
36
+ return "define :#{name}, #{number}"
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,28 @@
1
+ require 'protobuf/generators/base'
2
+ require 'protobuf/generators/group_generator'
3
+
4
+ module Protobuf
5
+ module Generators
6
+ class ExtensionGenerator < Base
7
+
8
+ def initialize(message_type, field_descriptors, indent_level)
9
+ super(nil, indent_level)
10
+ @message_type = modulize(message_type)
11
+ @field_descriptors = field_descriptors
12
+ end
13
+
14
+ def compile
15
+ run_once(:compile) do
16
+ print_class(@message_type, :message) do
17
+ group = GroupGenerator.new(current_indent)
18
+ group.add_extension_fields(@field_descriptors)
19
+ group.order = [ :extension_field ]
20
+ print group.to_s
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,132 @@
1
+ require 'protobuf/generators/base'
2
+
3
+ module Protobuf
4
+ module Generators
5
+ class FieldGenerator < Base
6
+
7
+ ##
8
+ # Constants
9
+ #
10
+ PROTO_INFINITY_DEFAULT = /^inf$/i.freeze
11
+ PROTO_NEGATIVE_INFINITY_DEFAULT = /^-inf$/i.freeze
12
+ PROTO_NAN_DEFAULT = /^nan$/i.freeze
13
+ RUBY_INFINITY_DEFAULT = '::Float::INFINITY'.freeze
14
+ RUBY_NEGATIVE_INFINITY_DEFAULT = '-::Float::INFINITY'.freeze
15
+ RUBY_NAN_DEFAULT = '::Float::NAN'.freeze
16
+
17
+ ##
18
+ # Attributes
19
+ #
20
+ attr_reader :field_options
21
+
22
+ def applicable_options
23
+ @applicable_options ||= field_options.map { |k, v| ":#{k} => #{v}" }
24
+ end
25
+
26
+ def default_value
27
+ @default_value ||= begin
28
+ if defaulted?
29
+ case descriptor.type.name
30
+ when :TYPE_ENUM then
31
+ enum_default_value
32
+ when :TYPE_STRING, :TYPE_BYTES then
33
+ string_default_value
34
+ when :TYPE_FLOAT, :TYPE_DOUBLE then
35
+ float_double_default_value
36
+ else
37
+ verbatim_default_value
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def defaulted?
44
+ descriptor.respond_to_has_and_present?(:default_value)
45
+ end
46
+
47
+ def deprecated?
48
+ descriptor.options.try(:deprecated?) { false }
49
+ end
50
+
51
+ def extension?
52
+ descriptor.respond_to_has_and_present?(:extendee)
53
+ end
54
+
55
+ def compile
56
+ run_once(:compile) do
57
+ field_definition = [ "#{label} #{type_name}", name, number, applicable_options ]
58
+ puts field_definition.flatten.compact.join(', ')
59
+ end
60
+ end
61
+
62
+ def label
63
+ @label ||= descriptor.label.name.to_s.downcase.sub(/label_/, '') # required, optional, repeated
64
+ end
65
+
66
+ def name
67
+ @name ||= ":#{descriptor.name}"
68
+ end
69
+
70
+ def number
71
+ @number ||= descriptor.number
72
+ end
73
+
74
+ def field_options
75
+ @field_options ||= begin
76
+ opts = {}
77
+ opts[:default] = default_value if defaulted?
78
+ opts[:packed] = 'true' if packed?
79
+ opts[:deprecated] = 'true' if deprecated?
80
+ opts[:extension] = 'true' if extension?
81
+ opts
82
+ end
83
+ end
84
+
85
+ def packed?
86
+ descriptor.options.try(:packed?) { false }
87
+ end
88
+
89
+ # Determine the field type
90
+ def type_name
91
+ @type_name ||= begin
92
+ case descriptor.type.name
93
+ when :TYPE_MESSAGE, :TYPE_ENUM, :TYPE_GROUP then
94
+ type_name = modulize(descriptor.type_name)
95
+ else
96
+ type_name = descriptor.type.name.to_s.downcase.sub(/type_/, '')
97
+ type_name = ":#{type_name}"
98
+ end
99
+ end
100
+ end
101
+
102
+ private
103
+
104
+ def enum_default_value
105
+ "#{type_name}::#{verbatim_default_value}"
106
+ end
107
+
108
+ def float_double_default_value
109
+ case verbatim_default_value
110
+ when PROTO_INFINITY_DEFAULT then
111
+ RUBY_INFINITY_DEFAULT
112
+ when PROTO_NEGATIVE_INFINITY_DEFAULT then
113
+ RUBY_NEGATIVE_INFINITY_DEFAULT
114
+ when PROTO_NAN_DEFAULT then
115
+ RUBY_NAN_DEFAULT
116
+ else
117
+ verbatim_default_value
118
+ end
119
+ end
120
+
121
+ def string_default_value
122
+ %Q{"#{verbatim_default_value.gsub(/'/, '\\\\\'')}"}
123
+ end
124
+
125
+ def verbatim_default_value
126
+ descriptor.default_value
127
+ end
128
+
129
+ end
130
+ end
131
+ end
132
+
@@ -0,0 +1,140 @@
1
+ require 'set'
2
+ require 'protobuf/generators/base'
3
+ require 'protobuf/generators/group_generator'
4
+
5
+ module Protobuf
6
+ module Generators
7
+ class FileGenerator < Base
8
+
9
+ attr_reader :output_file
10
+
11
+ def initialize(*args)
12
+ super
13
+ @output_file = ::Google::Protobuf::Compiler::CodeGeneratorResponse::File.new(:name => file_name)
14
+ @extension_fields = Hash.new { |h, k| h[k] = [] }
15
+ @known_messages = []
16
+ @dangling_messages = {}
17
+ end
18
+
19
+ def file_name
20
+ convert_filename(descriptor.name, false)
21
+ end
22
+
23
+ def compile
24
+ run_once(:compile) do
25
+ map_extensions(descriptor, [ descriptor.package ])
26
+ extract_dangling_extensions
27
+
28
+ print_file_comment
29
+ print_generic_requires
30
+ print_import_requires
31
+
32
+ print_package do
33
+ group = GroupGenerator.new(current_indent)
34
+ group.add_enums(descriptor.enum_type, :namespace => [ descriptor.package ])
35
+ group.add_message_declarations(descriptor.message_type)
36
+ group.add_messages(descriptor.message_type, :extension_fields => @extension_fields, :namespace => [ descriptor.package ])
37
+ group.add_extended_messages(@unknown_extensions)
38
+ group.add_services(descriptor.service)
39
+
40
+ group.add_header(:enum, 'Enum Classes')
41
+ group.add_header(:message_declaration, 'Message Classes')
42
+ group.add_header(:message, 'Message Fields')
43
+ group.add_header(:extended_message, 'Extended Message Fields')
44
+ group.add_header(:service, 'Service Classes')
45
+ print group.to_s
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+ def extract_dangling_extensions
52
+ @unknown_extensions = @extension_fields.select do |k, v|
53
+ ! @known_messages.include?(k)
54
+ end
55
+ end
56
+
57
+ def generate_output_file
58
+ compile
59
+ output_file.content = to_s
60
+ output_file
61
+ end
62
+
63
+ # Recursively map out all extensions known in this file.
64
+ # The key is the type_name of the message being extended, and
65
+ # the value is an array of field descriptors.
66
+ #
67
+ def map_extensions(descriptor, namespaces)
68
+ # Record all the message descriptor name's we encounter (should be the whole tree).
69
+ if descriptor.is_a?(::Google::Protobuf::DescriptorProto)
70
+ if fully_qualified_token?(descriptor.name)
71
+ @known_messages << descriptor.name
72
+ else
73
+ fully_qualified_namespace = ".#{namespaces.join('.')}"
74
+ @known_messages << fully_qualified_namespace
75
+ end
76
+ end
77
+
78
+ descriptor.extension.each do |field_descriptor|
79
+ @extension_fields[field_descriptor.extendee] << field_descriptor
80
+ end
81
+
82
+ if descriptor.respond_to_has_and_present?(:message_type)
83
+ descriptor.message_type.each do |message_descriptor|
84
+ map_extensions(message_descriptor, (namespaces + [ message_descriptor.name ]))
85
+ end
86
+ end
87
+
88
+ if descriptor.respond_to_has_and_present?(:nested_type)
89
+ descriptor.nested_type.each do |nested_descriptor|
90
+ map_extensions(nested_descriptor, (namespaces + [ nested_descriptor.name ]))
91
+ end
92
+ end
93
+ end
94
+
95
+ def print_file_comment
96
+ puts "##"
97
+ puts "# This file is auto-generated. DO NOT EDIT!"
98
+ puts "#"
99
+ end
100
+
101
+ def print_generic_requires
102
+ print_require("protobuf/message")
103
+ print_require("protobuf/rpc/service") if descriptor.service.count > 0
104
+ puts
105
+ end
106
+
107
+ def print_import_requires
108
+ if descriptor.dependency.count > 0
109
+ header "Imports"
110
+
111
+ descriptor.dependency.each do |dependency|
112
+ print_require(convert_filename(dependency))
113
+ end
114
+
115
+ puts
116
+ end
117
+ end
118
+
119
+ def print_package(&block)
120
+ final = lambda { block.call }
121
+ namespaces = descriptor.package.split('.')
122
+ namespaces.reverse.inject(final) { |previous, namespace|
123
+ lambda { print_module(namespace, &previous) }
124
+ }.call
125
+ end
126
+
127
+ private
128
+
129
+ def convert_filename(filename, for_require = true)
130
+ filename.sub(/\.proto/, (for_require ? '.pb' : '.pb.rb'))
131
+ end
132
+
133
+ def fully_qualified_token?(token)
134
+ token[0] == '.'
135
+ end
136
+
137
+ end
138
+ end
139
+ end
140
+