protobuf_descriptor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/ChangeLog.rdoc +4 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +57 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.rdoc +51 -0
  11. data/Rakefile +46 -0
  12. data/lib/protobuf_descriptor/enum_descriptor.rb +35 -0
  13. data/lib/protobuf_descriptor/file_descriptor.rb +130 -0
  14. data/lib/protobuf_descriptor/has_parent.rb +19 -0
  15. data/lib/protobuf_descriptor/message_descriptor.rb +167 -0
  16. data/lib/protobuf_descriptor/named_child.rb +21 -0
  17. data/lib/protobuf_descriptor/named_collection.rb +45 -0
  18. data/lib/protobuf_descriptor/service_descriptor.rb +94 -0
  19. data/lib/protobuf_descriptor/version.rb +4 -0
  20. data/lib/protobuf_descriptor.rb +95 -0
  21. data/protobuf_descriptor.gemspec +27 -0
  22. data/spec/enum_descriptor_spec.rb +45 -0
  23. data/spec/field_descriptor_spec.rb +24 -0
  24. data/spec/file_descriptor_spec.rb +52 -0
  25. data/spec/message_descriptor_spec.rb +43 -0
  26. data/spec/method_descriptor_spec.rb +17 -0
  27. data/spec/protobuf_descriptor_spec.rb +75 -0
  28. data/spec/protoc_generator_spec.rb +20 -0
  29. data/spec/protos/generator_test/aaa.proto +13 -0
  30. data/spec/protos/generator_test/foo/aab.proto +5 -0
  31. data/spec/protos/generator_test/java_package.proto +7 -0
  32. data/spec/protos/generator_test/outer_class_name.proto +7 -0
  33. data/spec/protos/service_rpc_test/wearabouts_api/multiple_files.proto +12 -0
  34. data/spec/protos/service_rpc_test/wearabouts_api/outer_class_proto.proto +12 -0
  35. data/spec/protos/service_rpc_test/wearabouts_api/user.proto +36 -0
  36. data/spec/protos/service_rpc_test/wearabouts_pb.proto +35 -0
  37. data/spec/protos/single_file_test/single_file.proto +169 -0
  38. data/spec/service_descriptor_spec.rb +13 -0
  39. data/spec/spec_helper.rb +145 -0
  40. data/spec/wire_generator_spec.rb +23 -0
  41. metadata +186 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86e4104ff69b390ba22f41af198f8f57100d6fae
4
+ data.tar.gz: 906471ce7f9431af23b952d547586dcf78cce699
5
+ SHA512:
6
+ metadata.gz: 2546c493431fe79360a7aaecec47a7104d5a76748a745ae43d6745b8a3b2a0c65357e447668c5c017c4e561848bc70850787fd6e543a4ce53cf0e2ea0e532cf9
7
+ data.tar.gz: f0cd6897c1c5c107c1aec223c4dbb2eac872a29a216a97857f1fc112fb7dacb83516361c832f571d4d41b328a9ba51cca41bc39cf44aa3446ab4eac950b85096
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.rdoc
3
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ # Ignore wire-compiler.jar, its auto-downloaded when running specs.
21
+ wire-compiler.jar
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup rdoc --title "protobuf_descriptor Documentation" --protected
data/ChangeLog.rdoc ADDED
@@ -0,0 +1,4 @@
1
+ === 0.1.0 / 2014-04-11
2
+
3
+ * Initial release:
4
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in protobuf_descriptor.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ protobuf_descriptor (0.1.0)
5
+ protobuf (~> 3.0.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.1.0)
11
+ i18n (~> 0.6, >= 0.6.9)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.1)
15
+ tzinfo (~> 1.1)
16
+ coderay (1.1.0)
17
+ diff-lcs (1.2.5)
18
+ i18n (0.6.9)
19
+ json (1.8.1)
20
+ method_source (0.8.2)
21
+ middleware (0.1.0)
22
+ minitest (5.3.2)
23
+ multi_json (1.9.2)
24
+ protobuf (3.0.4)
25
+ activesupport (>= 3.2)
26
+ middleware
27
+ multi_json
28
+ thor
29
+ pry (0.9.12.6)
30
+ coderay (~> 1.0)
31
+ method_source (~> 0.8)
32
+ slop (~> 3.4)
33
+ rspec (2.14.1)
34
+ rspec-core (~> 2.14.0)
35
+ rspec-expectations (~> 2.14.0)
36
+ rspec-mocks (~> 2.14.0)
37
+ rspec-core (2.14.8)
38
+ rspec-expectations (2.14.5)
39
+ diff-lcs (>= 1.1.3, < 2.0)
40
+ rspec-mocks (2.14.6)
41
+ rubygems-tasks (0.2.4)
42
+ slop (3.5.0)
43
+ thor (0.19.1)
44
+ thread_safe (0.3.3)
45
+ tzinfo (1.1.0)
46
+ thread_safe (~> 0.1)
47
+ yard (0.8.7.4)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ protobuf_descriptor!
54
+ pry (~> 0.9.12.6)
55
+ rspec (~> 2.4)
56
+ rubygems-tasks (~> 0.2)
57
+ yard (~> 0.8)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Hsiu-Fan Wang
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ = protobuf_descriptor
2
+
3
+ * {Homepage}[https://rubygems.org/gems/protobuf_descriptor]
4
+ * {Documentation}[http://rubydoc.info/gems/protobuf_descriptor/frames]
5
+
6
+ == Description
7
+
8
+ Protobuf_descriptor provides helper methods to make working with Google Protocol
9
+ Buffer descriptors easier, go figure.. It handles type resolution, and computing
10
+ type names (both within protocol buffers and in the generated output).
11
+
12
+ == Examples
13
+
14
+ Given the +descriptor.desc+ generated by the protocol buffer compiler, you
15
+ can introspect the various data types. This example references the descriptor
16
+ that would be generated by compiling
17
+ {single_file.proto}[https://github.com/hfwang/protobuf_descriptor/blob/master/spec/protos/single_file_test/single_file.proto]
18
+
19
+ require 'protobuf_descriptor'
20
+ descriptor = ProtobufDescriptor.load("descriptor.desc")
21
+
22
+ # Load a single file by its filename/basename
23
+ file_descriptor = descriptor[:single_file]
24
+
25
+ # Grab a handle to an enum, or a message
26
+ file_descriptor.messages[:FieldOptions]
27
+ file_descriptor.enums[:UnnestedEnum]
28
+
29
+ # Also allows resolving types by their fully qualified name:
30
+ descriptor.resolve_type(".porkbuns.UnnestedEnum") # note the leading "."
31
+ # or even doing so relative to another enum
32
+ descriptor.resolve_type("CType", ".porkbuns.FieldOptions")
33
+
34
+ For even more gory details, please peruse the actual
35
+ {documentation}[link:ProtobufDescriptor.html].
36
+
37
+ == Requirements
38
+
39
+ I've only tested this on Ruby 1.9.3+. If it works for you on an older version of
40
+ Ruby, let me know. You most likely want to install the
41
+ {Google Protocol Buffer library}[https://code.google.com/p/protobuf/].
42
+
43
+ == Install
44
+
45
+ $ gem install protobuf_descriptor
46
+
47
+ == Copyright
48
+
49
+ Copyright (c) 2014 Hsiu-Fan Wang
50
+
51
+ See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+
6
+ begin
7
+ require 'rubygems/tasks'
8
+
9
+ Gem::Tasks.new
10
+ rescue LoadError => e
11
+ warn e.message
12
+ warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
13
+ end
14
+
15
+ begin
16
+ require 'rspec/core/rake_task'
17
+
18
+ RSpec::Core::RakeTask.new
19
+ rescue LoadError => e
20
+ task :spec do
21
+ abort "Please run `gem install rspec` to install RSpec."
22
+ end
23
+ end
24
+
25
+ task :test => :spec
26
+ task :default => :spec
27
+
28
+ begin
29
+ gem 'yard', '~> 0.8'
30
+ require 'yard'
31
+
32
+ YARD::Rake::YardocTask.new
33
+ rescue LoadError => e
34
+ task :yard do
35
+ abort "Please run `gem install yard` to install YARD."
36
+ end
37
+ end
38
+ task :doc => :yard
39
+
40
+ task :spec => ["wire-compiler.jar"] do |t|
41
+ # Declare this to ensure wire-compiler is downloaded
42
+ end
43
+
44
+ file "wire-compiler.jar" do |t|
45
+ sh 'wget --no-check-certificate --output-document="wire-compiler.jar" "http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.wire&a=wire-compiler&v=LATEST&c=jar-with-dependencies"'
46
+ end
@@ -0,0 +1,35 @@
1
+ require "active_support"
2
+ require "protobuf_descriptor/named_child"
3
+ require "active_support/core_ext/module/delegation"
4
+
5
+ class ProtobufDescriptor
6
+ # Describes an enum type.
7
+ #
8
+ # See {+EnumDescriptorProto+}[https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto#84]
9
+ class EnumDescriptor
10
+ # The containing FileDescriptor[link:FileDescriptor.html]
11
+ # or MessageDescriptor[link:MessageDescriptor.html] that
12
+ # defines this enum.
13
+ attr_reader :parent
14
+
15
+ # The +EnumDescriptorProto+ this +EnumDescriptor+ is wrapping.
16
+ attr_reader :enum_descriptor_proto
17
+
18
+ def initialize(parent, enum_descriptor_proto)
19
+ @parent = parent
20
+ @enum_descriptor_proto = enum_descriptor_proto
21
+ end
22
+
23
+ # The name of the enum
24
+ def name; enum_descriptor_proto.name; end
25
+
26
+ # The possible values of the enum
27
+ def value; enum_descriptor_proto.value; end
28
+ alias_method :values, :value
29
+
30
+ # The +EnumOptions+ defined for this enum
31
+ def options; enum_descriptor_proto.options; end
32
+
33
+ include NamedChild
34
+ end
35
+ end
@@ -0,0 +1,130 @@
1
+ require "protobuf_descriptor/enum_descriptor"
2
+ require "protobuf_descriptor/message_descriptor"
3
+ require "protobuf_descriptor/service_descriptor"
4
+
5
+ require "active_support"
6
+ require "active_support/core_ext/object/blank"
7
+ require "active_support/core_ext/string/inflections"
8
+
9
+ class ProtobufDescriptor
10
+ # Describes a complete .proto file.
11
+ #
12
+ # See {+FileDescriptorProto+}[https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto#56]
13
+ class FileDescriptor
14
+ # The parent FileDescriptorSet[link:ProtobufDescriptor.html]
15
+ attr_reader :file_descriptor_set
16
+
17
+ # The +FileDescriptorProto+ this +FileDescriptor+ is wrapping.
18
+ attr_reader :file_descriptor_proto
19
+
20
+ # List of the message types that are defined at the top level of this file,
21
+ # as a NamedCollection of
22
+ # MessageDescriptors[link:MessageDescriptor.html]
23
+ attr_reader :message_type
24
+
25
+ # List of the enum types that are defined at the top level of this file,
26
+ # as a NamedCollection of
27
+ # EnumDescriptors[link:EnumDescriptor.html]
28
+ attr_reader :enum_type
29
+
30
+ # List of the services that are defined at the top level of this file, as a
31
+ # NamedCollection of
32
+ # ServiceDescriptors[link:ServiceDescriptor.html]
33
+ attr_reader :service
34
+
35
+ def initialize(file_descriptor_set, file_descriptor_proto) #:nodoc:
36
+ # This is basically a parent pointer.
37
+ @file_descriptor_set = file_descriptor_set
38
+ @file_descriptor_proto = file_descriptor_proto
39
+
40
+ @message_type = ProtobufDescriptor::NamedCollection.new(
41
+ file_descriptor_proto.message_type.map { |m|
42
+ ProtobufDescriptor::MessageDescriptor.new(self, m)
43
+ })
44
+ @enum_type = ProtobufDescriptor::NamedCollection.new(
45
+ file_descriptor_proto.enum_type.map { |m|
46
+ ProtobufDescriptor::EnumDescriptor.new(self, m)
47
+ })
48
+ @service = ProtobufDescriptor::NamedCollection.new(
49
+ file_descriptor_proto.service.map { |m|
50
+ ProtobufDescriptor::ServiceDescriptor.new(self, m)
51
+ })
52
+ end
53
+
54
+ alias_method :parent, :file_descriptor_set
55
+ alias_method :message_types, :message_type
56
+ alias_method :messages, :message_type
57
+ alias_method :enum_types, :enum_type
58
+ alias_method :enums, :enum_types
59
+ alias_method :services, :service
60
+
61
+ # Set of all top-level messages, enums and services that are defined inside
62
+ # of this file
63
+ def children
64
+ @children ||= ProtobufDescriptor::NamedCollection.new(
65
+ @message_type.collection + @enum_type.collection + @service.collection)
66
+ end
67
+
68
+ # Filename relative to root of source tree.
69
+ def name
70
+ file_descriptor_proto.name
71
+ end
72
+
73
+ # The package name defined by the .proto file. E.G. "foo", "foo.bar", etc.
74
+ def package
75
+ file_descriptor_proto.package
76
+ end
77
+
78
+ # The Java package where classes generated from this .proto will be
79
+ # placed. By default, the proto package is used, but this is often
80
+ # inappropriate because proto packages do not normally start with backwards
81
+ # domain names.
82
+ def java_package
83
+ if file_descriptor_proto.has_field?(:options) && file_descriptor_proto.options.java_package.present?
84
+ return file_descriptor_proto.options.java_package
85
+ else
86
+ return file_descriptor_proto.package
87
+ end
88
+ end
89
+
90
+ # If set, all the classes from the .proto file are wrapped in a single
91
+ # outer class with the given name. This applies to both Proto1
92
+ # (equivalent to the old "--one_java_file" option) and Proto2 (where
93
+ # a .proto always translates to a single class, but you may want to
94
+ # explicitly choose the class name).
95
+ def java_outer_classname
96
+ if file_descriptor_proto.has_field?(:options) && file_descriptor_proto.options.java_multiple_files.present?
97
+ return nil
98
+ elsif file_descriptor_proto.has_field?(:options) && file_descriptor_proto.options.java_outer_classname.present?
99
+ return file_descriptor_proto.options.java_outer_classname
100
+ else
101
+ basename = name.split('/').last
102
+ basename = basename.gsub('.proto', '')
103
+ return basename.camelize
104
+ end
105
+ end
106
+
107
+ # Returns the fully qualified name, as used by the +resolve_type+ methods.
108
+ def fully_qualified_name
109
+ return ".#{self.package}"
110
+ end
111
+
112
+ # Returns the fully qualified Java class name.
113
+ def fully_qualified_java_name
114
+ return [java_package, java_outer_classname].compact.join('.')
115
+ end
116
+
117
+ # Returns the fully qualified Java name as Wire would generate it. Wire
118
+ # never wraps the definitions in a class named after the .proto file
119
+ # (essentially behaving as if +java_outer_classname+ were always true)
120
+ def fully_qualified_wire_name
121
+ return java_package
122
+ end
123
+
124
+ # Returns the fully qualified Ruby class name as generated by various
125
+ # protobuf gems.
126
+ def fully_qualified_ruby_name
127
+ return "::#{self.package.gsub('.', '::')}"
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,19 @@
1
+ class ProtobufDescriptor
2
+ module HasParent
3
+ def file_descriptor
4
+ p = self.parent
5
+ while p.class.name != "ProtobufDescriptor::FileDescriptor"
6
+ p = p.parent
7
+ end
8
+ return p
9
+ end
10
+
11
+ def protobuf_descriptor
12
+ p = self.parent
13
+ while p.class.name != "ProtobufDescriptor"
14
+ p = p.parent
15
+ end
16
+ return p
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,167 @@
1
+ require "protobuf_descriptor/enum_descriptor"
2
+ require "protobuf_descriptor/has_parent"
3
+ require "protobuf_descriptor/named_child"
4
+ require "protobuf_descriptor/named_collection"
5
+
6
+ require "active_support"
7
+ require "active_support/core_ext/module/delegation"
8
+
9
+ class ProtobufDescriptor
10
+ # Describes a message type.
11
+ #
12
+ # See DescriptorProto[https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto#84]
13
+ class MessageDescriptor
14
+ # Describes a field within a message.
15
+ #
16
+ # See FieldDescriptorProto[https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto#103]
17
+ class FieldDescriptor
18
+ # The parent MessageDescriptor[link:MessageDescriptor.html]
19
+ attr_reader :parent
20
+ # The +FieldDescriptorProto+ this +FieldDescriptor+ is wrapping.
21
+ attr_reader :field_descriptor_proto
22
+
23
+ def initialize(parent, field_descriptor_proto)
24
+ @parent = parent
25
+ @field_descriptor_proto = field_descriptor_proto
26
+ end
27
+
28
+ # The +FieldOptions+ for this field
29
+ def options
30
+ field_descriptor_proto.options
31
+ end
32
+
33
+ # Default value for this field.
34
+ # * For numeric types, contains the original text representation of the
35
+ # value.
36
+ # * For booleans, "true" or "false".
37
+ # * For strings, contains the default text contents (not escaped in any
38
+ # way).
39
+ # * For bytes, contains the C escaped value. All bytes >= 128 are
40
+ # escaped.
41
+ def default_value
42
+ field_descriptor_proto.default_value
43
+ end
44
+
45
+ # For extensions, this is the name of the type being extended. It is
46
+ # resolved in the same manner as type_name.
47
+ def extendee
48
+ field_descriptor_proto.extendee
49
+ end
50
+
51
+ # For message and enum types, this is the name of the type. If the name
52
+ # starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
53
+ # rules are used to find the type (i.e. first the nested types within this
54
+ # message are searched, then within the parent, on up to the root
55
+ # namespace).
56
+ #
57
+ # Note: the protocol buffer compiler always emits the fully qualified name!
58
+ def type_name
59
+ field_descriptor_proto.type_name
60
+ end
61
+
62
+ # Whether the field is optional/required/repeated.
63
+ def label
64
+ field_descriptor_proto.label
65
+ end
66
+
67
+ # The tag number of this field.
68
+ def number
69
+ field_descriptor_proto.number
70
+ end
71
+
72
+ # The name of this field.
73
+ def name
74
+ field_descriptor_proto.name
75
+ end
76
+
77
+ include ProtobufDescriptor::HasParent
78
+
79
+ # If type_name is set, this need not be set. If both this and type_name
80
+ # are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
81
+ def field_type
82
+ field_descriptor_proto.type
83
+ end
84
+
85
+ # Resolves the field's +type_name+, returning the
86
+ # MessageDescriptor[link:MessageDescriptor.html] or
87
+ # EnumDescriptor[link:EnumDescriptor.html] that this field will represent.
88
+ def resolve_type
89
+ protobuf_descriptor.resolve_type_name(self.type_name, self.parent)
90
+ end
91
+ end
92
+
93
+ # The containing FileDescriptor[link:FileDescriptor.html]
94
+ # or MessageDescriptor[link:MessageDescriptor.html] that
95
+ # defines this message.
96
+ attr_reader :parent
97
+
98
+ # The +MessageDescriptorProto+ this +MessageDescriptor+ is wrapping.
99
+ attr_reader :message_descriptor_proto
100
+
101
+ # The messages that are defined at the top level of this message, as a
102
+ # NamedCollection of MessageDescriptors[link:MessageDescriptor.html]
103
+ attr_reader :nested_type
104
+
105
+ # The enums that are defined at the top level of this message, as a
106
+ # NamedCollection of EnumDescriptors[link:EnumDescriptor.html]
107
+ attr_reader :enum_type
108
+
109
+ # The fields of this message, as a NamedCollection of
110
+ # FieldDescriptors[link:MessageDescriptor/FieldDescriptor.html]
111
+ attr_reader :field
112
+
113
+ def initialize(parent, message_descriptor_proto)
114
+ @parent = parent
115
+ @message_descriptor_proto = message_descriptor_proto
116
+ @nested_type = ProtobufDescriptor::NamedCollection.new(
117
+ message_descriptor_proto.nested_type.map { |m|
118
+ ProtobufDescriptor::MessageDescriptor.new(self, m)
119
+ })
120
+ @enum_type = ProtobufDescriptor::NamedCollection.new(
121
+ message_descriptor_proto.enum_type.map { |m|
122
+ ProtobufDescriptor::EnumDescriptor.new(self, m)
123
+ })
124
+ @field = ProtobufDescriptor::NamedCollection.new(
125
+ message_descriptor_proto.field.map { |m|
126
+ ProtobufDescriptor::MessageDescriptor::FieldDescriptor.new(self, m)
127
+ })
128
+ end
129
+
130
+ # The +MessageOptions+ defined for this message.
131
+ def options
132
+ message_descriptor_proto.options
133
+ end
134
+
135
+ # The extension ranges defined for this message
136
+ def extension_range
137
+ message_descriptor_proto.extension_range
138
+ end
139
+
140
+ # The extensions defined for this message
141
+ def extension
142
+ message_descriptor_proto.extension
143
+ end
144
+
145
+ # The name of the message
146
+ def name
147
+ message_descriptor_proto.name
148
+ end
149
+
150
+ alias_method :fields, :field
151
+ alias_method :extensions, :extension
152
+ alias_method :nested_types, :nested_type
153
+ alias_method :messages, :nested_type
154
+ alias_method :enum_types, :enum_type
155
+ alias_method :enums, :enum_type
156
+ alias_method :extension_ranges, :extension_range
157
+
158
+ include ProtobufDescriptor::NamedChild
159
+
160
+ # Set of all top-level messages ahnd enums that are defined within this
161
+ # message.
162
+ def children
163
+ @children ||= ProtobufDescriptor::NamedCollection.new(
164
+ @nested_type.collection + @enum_type.collection)
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,21 @@
1
+ class ProtobufDescriptor
2
+ # A mixin module that adds tasty fully qualified name methods to objects that
3
+ # have a name and a parent.
4
+ module NamedChild
5
+ def fully_qualified_name
6
+ return "#{parent.fully_qualified_name}.#{self.name}"
7
+ end
8
+
9
+ def fully_qualified_java_name
10
+ return "#{parent.fully_qualified_java_name}.#{self.name}"
11
+ end
12
+
13
+ def fully_qualified_wire_name
14
+ return "#{parent.fully_qualified_wire_name}.#{self.name}"
15
+ end
16
+
17
+ def fully_qualified_ruby_name
18
+ return "#{parent.fully_qualified_ruby_name}::#{self.name}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,45 @@
1
+ require 'forwardable'
2
+
3
+ class ProtobufDescriptor
4
+ # Array wrapper that also supports lookup by "name"
5
+ #
6
+ # By default all members must respond to name, but this behavior can be
7
+ # overriden by passing a block in the initializer.
8
+ class NamedCollection
9
+ attr_accessor :collection, :matcher
10
+
11
+ include Enumerable
12
+ extend Forwardable
13
+
14
+ def_delegators :@collection, :each, :<<, :size, :length
15
+
16
+ def initialize(collection, &matcher)
17
+ @collection = []
18
+ collection.each { |c| @collection << c }
19
+
20
+ if block_given?
21
+ @matcher = matcher
22
+ else
23
+ @matcher = lambda { |name, member| return member.name == name }
24
+ end
25
+ end
26
+
27
+ def [](index)
28
+ if Fixnum === index
29
+ return collection[index]
30
+ else
31
+ return find_by_name(index)
32
+ end
33
+ end
34
+
35
+ def find_by_name(name)
36
+ return collection.find { |member|
37
+ matcher.call(name.to_s, member)
38
+ }
39
+ end
40
+
41
+ def to_a
42
+ return self.collection.to_a
43
+ end
44
+ end
45
+ end