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
@@ -0,0 +1,169 @@
1
+ package porkbuns;
2
+
3
+ // The following is copied from
4
+ // https://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/descriptor.proto
5
+ enum UnnestedEnum {
6
+ // Default mode.
7
+ STRING = 0;
8
+ CORD = 1;
9
+ STRING_PIECE = 2;
10
+ }
11
+
12
+ message FieldOptions {
13
+ // The ctype option instructs the C++ code generator to use a different
14
+ // representation of the field than it normally would. See the specific
15
+ // options below. This option is not yet implemented in the open source
16
+ // release -- sorry, we'll try to include it in a future version!
17
+ optional CType ctype = 1 [default = STRING];
18
+ enum CType {
19
+ // Default mode.
20
+ STRING = 0;
21
+
22
+ CORD = 1;
23
+
24
+ STRING_PIECE = 2;
25
+ }
26
+ // The packed option can be enabled for repeated primitive fields to enable
27
+ // a more efficient representation on the wire. Rather than repeatedly
28
+ // writing the tag and type for each element, the entire array is encoded as
29
+ // a single length-delimited blob.
30
+ optional bool packed = 2;
31
+
32
+
33
+
34
+ // Should this field be parsed lazily? Lazy applies only to message-type
35
+ // fields. It means that when the outer message is initially parsed, the
36
+ // inner message's contents will not be parsed but instead stored in encoded
37
+ // form. The inner message will actually be parsed when it is first accessed.
38
+ //
39
+ // This is only a hint. Implementations are free to choose whether to use
40
+ // eager or lazy parsing regardless of the value of this option. However,
41
+ // setting this option true suggests that the protocol author believes that
42
+ // using lazy parsing on this field is worth the additional bookkeeping
43
+ // overhead typically needed to implement it.
44
+ //
45
+ // This option does not affect the public interface of any generated code;
46
+ // all method signatures remain the same. Furthermore, thread-safety of the
47
+ // interface is not affected by this option; const methods remain safe to
48
+ // call from multiple threads concurrently, while non-const methods continue
49
+ // to require exclusive access.
50
+ //
51
+ //
52
+ // Note that implementations may choose not to check required fields within
53
+ // a lazy sub-message. That is, calling IsInitialized() on the outher message
54
+ // may return true even if the inner message has missing required fields.
55
+ // This is necessary because otherwise the inner message would have to be
56
+ // parsed in order to perform the check, defeating the purpose of lazy
57
+ // parsing. An implementation which chooses not to check required fields
58
+ // must be consistent about it. That is, for any particular sub-message, the
59
+ // implementation must either *always* check its required fields, or *never*
60
+ // check its required fields, regardless of whether or not the message has
61
+ // been parsed.
62
+ optional bool lazy = 5 [default=false];
63
+
64
+ // Is this field deprecated?
65
+ // Depending on the target platform, this can emit Deprecated annotations
66
+ // for accessors, or it will be completely ignored; in the very least, this
67
+ // is a formalization for deprecating fields.
68
+ optional bool deprecated = 3 [default=false];
69
+
70
+ // EXPERIMENTAL. DO NOT USE.
71
+ // For "map" fields, the name of the field in the enclosed type that
72
+ // is the key for this map. For example, suppose we have:
73
+ // message Item {
74
+ // required string name = 1;
75
+ // required string value = 2;
76
+ // }
77
+ // message Config {
78
+ // repeated Item items = 1 [experimental_map_key="name"];
79
+ // }
80
+ // In this situation, the map key for Item will be set to "name".
81
+ // TODO: Fully-implement this, then remove the "experimental_" prefix.
82
+ optional string experimental_map_key = 9;
83
+
84
+ // For Google-internal migration only. Do not use.
85
+ optional bool weak = 10 [default=false];
86
+
87
+ // The parser stores options it doesn't recognize here. See above.
88
+ repeated UninterpretedOption uninterpreted_option = 999;
89
+
90
+ // Clients can define custom options in extensions of this message. See above.
91
+ extensions 1000 to max;
92
+ }
93
+
94
+ message EnumOptions {
95
+
96
+ // Set this option to false to disallow mapping different tag names to a same
97
+ // value.
98
+ optional bool allow_alias = 2 [default=true];
99
+
100
+ // The parser stores options it doesn't recognize here. See above.
101
+ repeated UninterpretedOption uninterpreted_option = 999;
102
+
103
+ // Clients can define custom options in extensions of this message. See above.
104
+ extensions 1000 to max;
105
+ }
106
+
107
+ message EnumValueOptions {
108
+ // The parser stores options it doesn't recognize here. See above.
109
+ repeated UninterpretedOption uninterpreted_option = 999;
110
+
111
+ // Clients can define custom options in extensions of this message. See above.
112
+ extensions 1000 to max;
113
+ }
114
+
115
+ message ServiceOptions {
116
+
117
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
118
+ // framework. We apologize for hoarding these numbers to ourselves, but
119
+ // we were already using them long before we decided to release Protocol
120
+ // Buffers.
121
+
122
+ // The parser stores options it doesn't recognize here. See above.
123
+ repeated UninterpretedOption uninterpreted_option = 999;
124
+
125
+ // Clients can define custom options in extensions of this message. See above.
126
+ extensions 1000 to max;
127
+ }
128
+
129
+ message MethodOptions {
130
+
131
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
132
+ // framework. We apologize for hoarding these numbers to ourselves, but
133
+ // we were already using them long before we decided to release Protocol
134
+ // Buffers.
135
+
136
+ // The parser stores options it doesn't recognize here. See above.
137
+ repeated UninterpretedOption uninterpreted_option = 999;
138
+
139
+ // Clients can define custom options in extensions of this message. See above.
140
+ extensions 1000 to max;
141
+ }
142
+
143
+ // A message representing a option the parser does not recognize. This only
144
+ // appears in options protos created by the compiler::Parser class.
145
+ // DescriptorPool resolves these when building Descriptor objects. Therefore,
146
+ // options protos in descriptor objects (e.g. returned by Descriptor::options(),
147
+ // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
148
+ // in them.
149
+ message UninterpretedOption {
150
+ // The name of the uninterpreted option. Each string represents a segment in
151
+ // a dot-separated name. is_extension is true iff a segment represents an
152
+ // extension (denoted with parentheses in options specs in .proto files).
153
+ // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
154
+ // "foo.(bar.baz).qux".
155
+ message NamePart {
156
+ required string name_part = 1;
157
+ required bool is_extension = 2;
158
+ }
159
+ repeated NamePart name = 2;
160
+
161
+ // The value of the uninterpreted option, in whatever type the tokenizer
162
+ // identified it as during parsing. Exactly one of these should be set.
163
+ optional string identifier_value = 3;
164
+ optional uint64 positive_int_value = 4;
165
+ optional int64 negative_int_value = 5;
166
+ optional double double_value = 6;
167
+ optional bytes string_value = 7;
168
+ optional string aggregate_value = 8;
169
+ }
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe ProtobufDescriptor::ServiceDescriptor do
4
+ describe "#methods" do
5
+ it "has right size" do
6
+ with_descriptor("service_rpc_test") do |descriptor|
7
+ service_descriptor = descriptor["wearabouts_api/user"].services[:UserService]
8
+ expect(service_descriptor).to be_a(ProtobufDescriptor::ServiceDescriptor)
9
+ expect(service_descriptor.methods).to have(3).items
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,145 @@
1
+ require 'rspec'
2
+ require "protobuf_descriptor"
3
+
4
+ require "fileutils"
5
+ require "pathname"
6
+ require "tempfile"
7
+
8
+ # "Parses" a java package returning a mapping of class/enum names to their fully
9
+ # qualified name.
10
+ #
11
+ # Raises if a class name occurs twice.
12
+ def ghetto_parse_java_package(dir)
13
+ tokens = [
14
+ # Wire enum
15
+ [:enum, /public\s+enum\s+(\w+)\s+implements\s+ProtoEnum\s+{/],
16
+ # Protoc Java enum
17
+ [:enum, /public\s+enum\s+(\w+)\s+implements\s+com\.google\.protobuf\.ProtocolMessageEnum\s+{/],
18
+ # This is used by the protocol buffer compiler to wrap all the protos
19
+ # defined in a single file.
20
+ [:namespace, /public\s+(?:(?:static|final)\s+)*class\s+(\w+)\s+{/],
21
+ # Wire message type
22
+ [:message, /public\s+(?:(?:static|final)\s+)*class\s+(\w+)\s+extends\s+Message\s+{/],
23
+ # Protoc java message
24
+ [:message, /public\s+(?:(?:static|final)\s+)*class\s+(\w+)\s+extends\s+com\.google\.protobuf\.GeneratedMessage\s+implements\s+(\w+)\s+{/],
25
+ [:open_brace, /{/],
26
+ [:close_brace, /}/],
27
+ [:eof, /\z/]]
28
+
29
+ found = {}
30
+
31
+ Dir.glob("#{dir}/**/*.java").each do |filename|
32
+ contents = File.read(filename)
33
+
34
+ package = contents.match(/package\s+([\w\.]+);/)
35
+ package = package[1] unless package.nil?
36
+
37
+ # puts "#{filename[dir.length..-1]}: package #{package}"
38
+
39
+ bits = [package]
40
+
41
+ offset = 0
42
+ while offset < contents.length
43
+ token, regex = tokens.min_by { |k, v|
44
+ match = v.match(contents, offset)
45
+ # Move offset off end of file so EOF matches first.
46
+ match.nil? ? contents.length + 1: match.begin(0)
47
+ }
48
+ match = regex.match(contents, offset)
49
+ offset = match.end(0)
50
+
51
+ # Build a stack of named components
52
+ case token
53
+ when :enum, :message
54
+ # If we find a named component, add it to the stack as well as
55
+ # generating its portion of the output.
56
+ bits.push(match[1])
57
+ raise "Type name #{match[1]} occurs twice!" if found[match[1]]
58
+ found[match[1]] = bits.compact.join('.')
59
+ when :namespace
60
+ bits.push(match[1])
61
+ when :open_brace
62
+ bits.push(nil)
63
+ when :close_brace
64
+ bits.pop
65
+ end
66
+
67
+ # puts "#{token}@#{offset} #{bits.inspect}"
68
+ end
69
+ end
70
+ return found
71
+ end
72
+
73
+ def with_temp_file(name="tempfile")
74
+ file = Tempfile.new(name)
75
+ begin
76
+ yield file
77
+ ensure
78
+ file.close
79
+ file.unlink
80
+ end
81
+ end
82
+
83
+ def compile_wire_protobuf(args={})
84
+ args = {
85
+ destination: ".",
86
+ source: ".",
87
+ extra_args: []
88
+ }.merge(args)
89
+
90
+ jar_path = File.realpath("#{File.dirname(__FILE__)}/../wire-compiler.jar")
91
+ command = ["java", "-jar", jar_path]
92
+ command << "--proto_path=#{args[:source]}"
93
+ command += args[:extra_args]
94
+ command << "--java_out=#{args[:destination]}"
95
+ command += Dir.glob("#{args[:source]}**/*.proto").map { |p|
96
+ Pathname.new(p).relative_path_from(Pathname.new(args[:source])).to_s
97
+ }
98
+ with_temp_file do |tmp_log|
99
+ rv = system(*command, out: [tmp_log.path, "a"], err: [tmp_log.path, "a"])
100
+
101
+ raise "Wire protobuf generation failed!\n#{File.read(tmp_log)}" unless rv
102
+ end
103
+ end
104
+
105
+ def generate_protobuf_descriptor(args={})
106
+ args = {
107
+ source: ".",
108
+ extra_args: [],
109
+ plugin: nil,
110
+ plugin_out: "",
111
+ out: "out.desc"
112
+ }.merge(args)
113
+ args[:source] += '/' unless args[:source].end_with?('/')
114
+
115
+ command = []
116
+ command << "protoc"
117
+ command << "-I#{args[:source]}"
118
+ if args[:plugin]
119
+ command << "--#{args[:plugin]}_out=#{args[:plugin_out]}"
120
+ end
121
+ command += args[:extra_args]
122
+ command << "--descriptor_set_out=#{args[:out]}"
123
+ command += Dir.glob("#{args[:source]}**/*.proto")
124
+
125
+ rv = system(*command)
126
+
127
+ raise "ProtobufDescriptor generation failed!" unless rv
128
+ end
129
+
130
+ def with_descriptor_file(source, args={})
131
+ with_temp_file do |f|
132
+ args = {
133
+ out: f.path,
134
+ source: "#{File.dirname(__FILE__)}/protos/#{source}/"
135
+ }.merge(args)
136
+ generate_protobuf_descriptor(args)
137
+ yield f
138
+ end
139
+ end
140
+
141
+ def with_descriptor(source, args={})
142
+ with_descriptor_file(source, args) do |f|
143
+ yield ProtobufDescriptor.decode_from(f)
144
+ end
145
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+ require "tmpdir"
3
+
4
+ describe "WireCompiler" do
5
+ # Compile the contents of the generator_tests proto dir, and then assert
6
+ # everything is where it should be.
7
+ it "computes fully-qualified class names correctly" do
8
+ Dir.mktmpdir do |dir|
9
+ # The following is to compile protos with wire, since its done as a
10
+ # separate process:
11
+ compile_wire_protobuf(source: "#{File.dirname(__FILE__)}/protos/generator_test/", destination: dir)
12
+ generated_classes = ghetto_parse_java_package(dir)
13
+
14
+ with_descriptor("generator_test") do |descriptor|
15
+ children = descriptor.all_descendants
16
+
17
+ children.each do |child|
18
+ expect(child.fully_qualified_wire_name).to eq(generated_classes[child.name])
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,186 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: protobuf_descriptor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Hsiu-Fan Wang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: protobuf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: active_support
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.12.6
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.12.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubygems-tasks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0.8'
97
+ description: Wraps the protobuf FileDescriptorSet messages with happy features like
98
+ type name resolution and the like.
99
+ email: hfwang@porkbuns.net
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .document
105
+ - .gitignore
106
+ - .rspec
107
+ - .yardopts
108
+ - ChangeLog.rdoc
109
+ - Gemfile
110
+ - Gemfile.lock
111
+ - LICENSE.txt
112
+ - README.rdoc
113
+ - Rakefile
114
+ - lib/protobuf_descriptor.rb
115
+ - lib/protobuf_descriptor/enum_descriptor.rb
116
+ - lib/protobuf_descriptor/file_descriptor.rb
117
+ - lib/protobuf_descriptor/has_parent.rb
118
+ - lib/protobuf_descriptor/message_descriptor.rb
119
+ - lib/protobuf_descriptor/named_child.rb
120
+ - lib/protobuf_descriptor/named_collection.rb
121
+ - lib/protobuf_descriptor/service_descriptor.rb
122
+ - lib/protobuf_descriptor/version.rb
123
+ - protobuf_descriptor.gemspec
124
+ - spec/enum_descriptor_spec.rb
125
+ - spec/field_descriptor_spec.rb
126
+ - spec/file_descriptor_spec.rb
127
+ - spec/message_descriptor_spec.rb
128
+ - spec/method_descriptor_spec.rb
129
+ - spec/protobuf_descriptor_spec.rb
130
+ - spec/protoc_generator_spec.rb
131
+ - spec/protos/generator_test/aaa.proto
132
+ - spec/protos/generator_test/foo/aab.proto
133
+ - spec/protos/generator_test/java_package.proto
134
+ - spec/protos/generator_test/outer_class_name.proto
135
+ - spec/protos/service_rpc_test/wearabouts_api/multiple_files.proto
136
+ - spec/protos/service_rpc_test/wearabouts_api/outer_class_proto.proto
137
+ - spec/protos/service_rpc_test/wearabouts_api/user.proto
138
+ - spec/protos/service_rpc_test/wearabouts_pb.proto
139
+ - spec/protos/single_file_test/single_file.proto
140
+ - spec/service_descriptor_spec.rb
141
+ - spec/spec_helper.rb
142
+ - spec/wire_generator_spec.rb
143
+ homepage: https://github.com/hfwang/protobuf_descriptor
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.0.6
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Protocol Buffer file descriptor parser
167
+ test_files:
168
+ - spec/enum_descriptor_spec.rb
169
+ - spec/field_descriptor_spec.rb
170
+ - spec/file_descriptor_spec.rb
171
+ - spec/message_descriptor_spec.rb
172
+ - spec/method_descriptor_spec.rb
173
+ - spec/protobuf_descriptor_spec.rb
174
+ - spec/protoc_generator_spec.rb
175
+ - spec/protos/generator_test/aaa.proto
176
+ - spec/protos/generator_test/foo/aab.proto
177
+ - spec/protos/generator_test/java_package.proto
178
+ - spec/protos/generator_test/outer_class_name.proto
179
+ - spec/protos/service_rpc_test/wearabouts_api/multiple_files.proto
180
+ - spec/protos/service_rpc_test/wearabouts_api/outer_class_proto.proto
181
+ - spec/protos/service_rpc_test/wearabouts_api/user.proto
182
+ - spec/protos/service_rpc_test/wearabouts_pb.proto
183
+ - spec/protos/single_file_test/single_file.proto
184
+ - spec/service_descriptor_spec.rb
185
+ - spec/spec_helper.rb
186
+ - spec/wire_generator_spec.rb