protobuf_descriptor 0.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 (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