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
@@ -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