ruby-protocol-buffers 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/protoc-gen-ruby +30 -0
- data/lib/protocol_buffers/compiler/file_descriptor_to_ruby.rb +10 -1
- data/lib/protocol_buffers/compiler/plugin.pb.rb +32 -0
- data/lib/protocol_buffers/compiler/plugin.proto +146 -0
- data/lib/protocol_buffers/runtime/decoder.rb +5 -2
- data/lib/protocol_buffers/runtime/encoder.rb +5 -2
- data/lib/protocol_buffers/runtime/field.rb +21 -6
- data/lib/protocol_buffers/runtime/message.rb +1 -1
- data/lib/protocol_buffers/version.rb +1 -1
- data/spec/compiler_spec.rb +35 -0
- data/spec/proto_files/depends.proto +4 -1
- data/spec/proto_files/featureful.pb.rb +45 -0
- data/spec/proto_files/featureful.proto +19 -0
- data/spec/proto_files/nested/child.proto +5 -0
- data/spec/runtime_spec.rb +21 -0
- metadata +14 -2
data/bin/protoc-gen-ruby
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'protocol_buffers/compiler/file_descriptor_to_ruby'
|
3
|
+
require 'protocol_buffers/compiler/plugin.pb'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
response = CodeGeneratorResponse.new
|
7
|
+
begin
|
8
|
+
request = CodeGeneratorRequest.parse($stdin)
|
9
|
+
|
10
|
+
request.proto_file.each do |file_descriptor|
|
11
|
+
next unless request.file_to_generate.include? file_descriptor.name
|
12
|
+
dumper = FileDescriptorToRuby.new(file_descriptor)
|
13
|
+
io = StringIO.new
|
14
|
+
dumper.write(io)
|
15
|
+
filename = File.join(File.dirname(file_descriptor.name),
|
16
|
+
File.basename(file_descriptor.name, '.proto') + '.pb.rb')
|
17
|
+
file = CodeGeneratorResponse::File.new(:name => filename, :content => io.string)
|
18
|
+
response.file << file
|
19
|
+
end
|
20
|
+
rescue => error
|
21
|
+
response.file.clear
|
22
|
+
response.error = "%s\n%s\n\nBacktrace:\n%s" % [
|
23
|
+
"Failed to generate a Ruby file",
|
24
|
+
error.message,
|
25
|
+
error.backtrace.join("\n")
|
26
|
+
]
|
27
|
+
$stderr.puts response.error
|
28
|
+
else
|
29
|
+
print response.to_s
|
30
|
+
end
|
@@ -24,7 +24,13 @@ require 'protocol_buffers'
|
|
24
24
|
HEADER
|
25
25
|
|
26
26
|
descriptor.dependency.each do |dep|
|
27
|
-
|
27
|
+
dir = File.dirname(dep)
|
28
|
+
filename = File.basename(dep, ".proto") + ".pb"
|
29
|
+
path = if dir == '.'
|
30
|
+
filename
|
31
|
+
else
|
32
|
+
File.join(dir, filename)
|
33
|
+
end
|
28
34
|
@io.write("begin; require '#{path}'; rescue LoadError; end\n")
|
29
35
|
end
|
30
36
|
@io.write("\n") unless descriptor.dependency.empty?
|
@@ -123,6 +129,9 @@ HEADER
|
|
123
129
|
message.field.each do |field|
|
124
130
|
typename = field_typename(field)
|
125
131
|
fieldline = %{#{LABEL_MAPPING[field.label]} #{typename}, :#{field.name}, #{field.number}}
|
132
|
+
if field.type == TYPE_GROUP
|
133
|
+
fieldline << %{, :group => true}
|
134
|
+
end
|
126
135
|
if field.default_value && field.default_value != ""
|
127
136
|
fieldline << %{, :default => #{default_value(field)}}
|
128
137
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
|
4
|
+
require 'protocol_buffers'
|
5
|
+
|
6
|
+
begin; require 'descriptor.pb'; rescue LoadError; end
|
7
|
+
|
8
|
+
# forward declarations
|
9
|
+
class CodeGeneratorRequest < ::ProtocolBuffers::Message; end
|
10
|
+
class CodeGeneratorResponse < ::ProtocolBuffers::Message; end
|
11
|
+
|
12
|
+
class CodeGeneratorRequest < ::ProtocolBuffers::Message
|
13
|
+
repeated :string, :file_to_generate, 1
|
14
|
+
optional :string, :parameter, 2
|
15
|
+
repeated ::FileDescriptorProto, :proto_file, 15
|
16
|
+
end
|
17
|
+
|
18
|
+
class CodeGeneratorResponse < ::ProtocolBuffers::Message
|
19
|
+
# forward declarations
|
20
|
+
class File < ::ProtocolBuffers::Message; end
|
21
|
+
|
22
|
+
# nested messages
|
23
|
+
class File < ::ProtocolBuffers::Message
|
24
|
+
optional :string, :name, 1
|
25
|
+
optional :string, :insertion_point, 2
|
26
|
+
optional :string, :content, 15
|
27
|
+
end
|
28
|
+
|
29
|
+
optional :string, :error, 1
|
30
|
+
repeated ::CodeGeneratorResponse::File, :file, 15
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
// Protocol Buffers - Google's data interchange format
|
2
|
+
// Copyright 2008 Google Inc. All rights reserved.
|
3
|
+
// http://code.google.com/p/protobuf/
|
4
|
+
//
|
5
|
+
// Redistribution and use in source and binary forms, with or without
|
6
|
+
// modification, are permitted provided that the following conditions are
|
7
|
+
// met:
|
8
|
+
//
|
9
|
+
// * Redistributions of source code must retain the above copyright
|
10
|
+
// notice, this list of conditions and the following disclaimer.
|
11
|
+
// * Redistributions in binary form must reproduce the above
|
12
|
+
// copyright notice, this list of conditions and the following disclaimer
|
13
|
+
// in the documentation and/or other materials provided with the
|
14
|
+
// distribution.
|
15
|
+
// * Neither the name of Google Inc. nor the names of its
|
16
|
+
// contributors may be used to endorse or promote products derived from
|
17
|
+
// this software without specific prior written permission.
|
18
|
+
//
|
19
|
+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
// Author: kenton@google.com (Kenton Varda)
|
32
|
+
//
|
33
|
+
// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to
|
34
|
+
// change.
|
35
|
+
//
|
36
|
+
// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
|
37
|
+
// just a program that reads a CodeGeneratorRequest from stdin and writes a
|
38
|
+
// CodeGeneratorResponse to stdout.
|
39
|
+
//
|
40
|
+
// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
|
41
|
+
// of dealing with the raw protocol defined here.
|
42
|
+
//
|
43
|
+
// A plugin executable needs only to be placed somewhere in the path. The
|
44
|
+
// plugin should be named "protoc-gen-$NAME", and will then be used when the
|
45
|
+
// flag "--${NAME}_out" is passed to protoc.
|
46
|
+
|
47
|
+
//package google.protobuf.compiler;
|
48
|
+
|
49
|
+
//import "google/protobuf/descriptor.proto";
|
50
|
+
import "descriptor.proto";
|
51
|
+
|
52
|
+
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
|
53
|
+
message CodeGeneratorRequest {
|
54
|
+
// The .proto files that were explicitly listed on the command-line. The
|
55
|
+
// code generator should generate code only for these files. Each file's
|
56
|
+
// descriptor will be included in proto_file, below.
|
57
|
+
repeated string file_to_generate = 1;
|
58
|
+
|
59
|
+
// The generator parameter passed on the command-line.
|
60
|
+
optional string parameter = 2;
|
61
|
+
|
62
|
+
// FileDescriptorProtos for all files in files_to_generate and everything
|
63
|
+
// they import. The files will appear in topological order, so each file
|
64
|
+
// appears before any file that imports it.
|
65
|
+
//
|
66
|
+
// protoc guarantees that all proto_files will be written after
|
67
|
+
// the fields above, even though this is not technically guaranteed by the
|
68
|
+
// protobuf wire format. This theoretically could allow a plugin to stream
|
69
|
+
// in the FileDescriptorProtos and handle them one by one rather than read
|
70
|
+
// the entire set into memory at once. However, as of this writing, this
|
71
|
+
// is not similarly optimized on protoc's end -- it will store all fields in
|
72
|
+
// memory at once before sending them to the plugin.
|
73
|
+
repeated FileDescriptorProto proto_file = 15;
|
74
|
+
}
|
75
|
+
|
76
|
+
// The plugin writes an encoded CodeGeneratorResponse to stdout.
|
77
|
+
message CodeGeneratorResponse {
|
78
|
+
// Error message. If non-empty, code generation failed. The plugin process
|
79
|
+
// should exit with status code zero even if it reports an error in this way.
|
80
|
+
//
|
81
|
+
// This should be used to indicate errors in .proto files which prevent the
|
82
|
+
// code generator from generating correct code. Errors which indicate a
|
83
|
+
// problem in protoc itself -- such as the input CodeGeneratorRequest being
|
84
|
+
// unparseable -- should be reported by writing a message to stderr and
|
85
|
+
// exiting with a non-zero status code.
|
86
|
+
optional string error = 1;
|
87
|
+
|
88
|
+
// Represents a single generated file.
|
89
|
+
message File {
|
90
|
+
// The file name, relative to the output directory. The name must not
|
91
|
+
// contain "." or ".." components and must be relative, not be absolute (so,
|
92
|
+
// the file cannot lie outside the output directory). "/" must be used as
|
93
|
+
// the path separator, not "\".
|
94
|
+
//
|
95
|
+
// If the name is omitted, the content will be appended to the previous
|
96
|
+
// file. This allows the generator to break large files into small chunks,
|
97
|
+
// and allows the generated text to be streamed back to protoc so that large
|
98
|
+
// files need not reside completely in memory at one time. Note that as of
|
99
|
+
// this writing protoc does not optimize for this -- it will read the entire
|
100
|
+
// CodeGeneratorResponse before writing files to disk.
|
101
|
+
optional string name = 1;
|
102
|
+
|
103
|
+
// If non-empty, indicates that the named file should already exist, and the
|
104
|
+
// content here is to be inserted into that file at a defined insertion
|
105
|
+
// point. This feature allows a code generator to extend the output
|
106
|
+
// produced by another code generator. The original generator may provide
|
107
|
+
// insertion points by placing special annotations in the file that look
|
108
|
+
// like:
|
109
|
+
// @@protoc_insertion_point(NAME)
|
110
|
+
// The annotation can have arbitrary text before and after it on the line,
|
111
|
+
// which allows it to be placed in a comment. NAME should be replaced with
|
112
|
+
// an identifier naming the point -- this is what other generators will use
|
113
|
+
// as the insertion_point. Code inserted at this point will be placed
|
114
|
+
// immediately above the line containing the insertion point (thus multiple
|
115
|
+
// insertions to the same point will come out in the order they were added).
|
116
|
+
// The double-@ is intended to make it unlikely that the generated code
|
117
|
+
// could contain things that look like insertion points by accident.
|
118
|
+
//
|
119
|
+
// For example, the C++ code generator places the following line in the
|
120
|
+
// .pb.h files that it generates:
|
121
|
+
// // @@protoc_insertion_point(namespace_scope)
|
122
|
+
// This line appears within the scope of the file's package namespace, but
|
123
|
+
// outside of any particular class. Another plugin can then specify the
|
124
|
+
// insertion_point "namespace_scope" to generate additional classes or
|
125
|
+
// other declarations that should be placed in this scope.
|
126
|
+
//
|
127
|
+
// Note that if the line containing the insertion point begins with
|
128
|
+
// whitespace, the same whitespace will be added to every line of the
|
129
|
+
// inserted text. This is useful for languages like Python, where
|
130
|
+
// indentation matters. In these languages, the insertion point comment
|
131
|
+
// should be indented the same amount as any inserted code will need to be
|
132
|
+
// in order to work correctly in that context.
|
133
|
+
//
|
134
|
+
// The code generator that generates the initial file and the one which
|
135
|
+
// inserts into it must both run as part of a single invocation of protoc.
|
136
|
+
// Code generators are executed in the order in which they appear on the
|
137
|
+
// command line.
|
138
|
+
//
|
139
|
+
// If |insertion_point| is present, |name| must also be present.
|
140
|
+
optional string insertion_point = 2;
|
141
|
+
|
142
|
+
// The file contents.
|
143
|
+
optional string content = 15;
|
144
|
+
}
|
145
|
+
repeated File file = 15;
|
146
|
+
}
|
@@ -12,6 +12,7 @@ module ProtocolBuffers
|
|
12
12
|
tag_int = Varint.decode(io)
|
13
13
|
tag = tag_int >> 3
|
14
14
|
wire_type = tag_int & 0b111
|
15
|
+
break if wire_type == 4
|
15
16
|
field = fields[tag]
|
16
17
|
|
17
18
|
if field && ( !( field.packed? || wire_type == field.wire_type ) || ( field.packed? && wire_type != 2 ) )
|
@@ -31,8 +32,10 @@ module ProtocolBuffers
|
|
31
32
|
value = LimitedIO.new(io, length)
|
32
33
|
when 5 # FIXED32
|
33
34
|
value = io.read(4)
|
34
|
-
when 3
|
35
|
-
|
35
|
+
when 3 # START_GROUP
|
36
|
+
value = io
|
37
|
+
when 4 # END_GROUP
|
38
|
+
break
|
36
39
|
else
|
37
40
|
raise(DecodeError, "unknown wire type: #{wire_type}")
|
38
41
|
end
|
@@ -49,6 +49,7 @@ module ProtocolBuffers
|
|
49
49
|
# write the tag
|
50
50
|
Varint.encode(io, tag)
|
51
51
|
self.serialize_field_value(io, wire_type, serialized)
|
52
|
+
Varint.encode(io, tag & ~3 | 4) if wire_type == 3
|
52
53
|
end
|
53
54
|
|
54
55
|
def self.serialize_field_value(io, wire_type, serialized)
|
@@ -61,8 +62,10 @@ module ProtocolBuffers
|
|
61
62
|
when 2 # LENGTH_DELIMITED
|
62
63
|
Varint.encode(io, serialized.bytesize)
|
63
64
|
io.write(serialized)
|
64
|
-
when 3
|
65
|
-
|
65
|
+
when 3 # START_GROUP
|
66
|
+
io.write(serialized)
|
67
|
+
when 4 # END_GROUP: never appear
|
68
|
+
raise(EncodeError, "Unexpected wire type END_GROUP")
|
66
69
|
else
|
67
70
|
raise(EncodeError, "unknown wire type: #{wire_type}")
|
68
71
|
end
|
@@ -107,7 +107,11 @@ module ProtocolBuffers
|
|
107
107
|
elsif type.ancestors.include?(ProtocolBuffers::Enum)
|
108
108
|
field = Field::EnumField.new(type, otype, name, tag, opts)
|
109
109
|
elsif type.ancestors.include?(ProtocolBuffers::Message)
|
110
|
-
|
110
|
+
if opts[:group]
|
111
|
+
field = Field::GroupField.new(type, otype, name, tag, opts)
|
112
|
+
else
|
113
|
+
field = Field::MessageField.new(type, otype, name, tag, opts)
|
114
|
+
end
|
111
115
|
else
|
112
116
|
raise("Type not found: #{type}")
|
113
117
|
end
|
@@ -237,9 +241,11 @@ module ProtocolBuffers
|
|
237
241
|
def wire_type
|
238
242
|
WireTypes::LENGTH_DELIMITED
|
239
243
|
end
|
244
|
+
end
|
240
245
|
|
241
|
-
|
242
|
-
|
246
|
+
module GROUP
|
247
|
+
def wire_type
|
248
|
+
WireTypes::START_GROUP
|
243
249
|
end
|
244
250
|
end
|
245
251
|
|
@@ -288,6 +294,10 @@ module ProtocolBuffers
|
|
288
294
|
def default_value
|
289
295
|
@default_value || @default_value = (@opts[:default] || "").freeze
|
290
296
|
end
|
297
|
+
|
298
|
+
def deserialize(value)
|
299
|
+
value.read
|
300
|
+
end
|
291
301
|
end
|
292
302
|
|
293
303
|
class StringField < BytesField
|
@@ -572,9 +582,7 @@ module ProtocolBuffers
|
|
572
582
|
end
|
573
583
|
end
|
574
584
|
|
575
|
-
class
|
576
|
-
include WireFormats::LENGTH_DELIMITED
|
577
|
-
|
585
|
+
class AggregateField < Field
|
578
586
|
attr_reader :proxy_class
|
579
587
|
|
580
588
|
def initialize(proxy_class, otype, name, tag, opts = {})
|
@@ -602,5 +610,12 @@ module ProtocolBuffers
|
|
602
610
|
end
|
603
611
|
end
|
604
612
|
|
613
|
+
class MessageField < AggregateField
|
614
|
+
include WireFormats::LENGTH_DELIMITED
|
615
|
+
end
|
616
|
+
|
617
|
+
class GroupField < AggregateField
|
618
|
+
include WireFormats::GROUP
|
619
|
+
end
|
605
620
|
end
|
606
621
|
end
|
@@ -498,7 +498,7 @@ module ProtocolBuffers
|
|
498
498
|
field = fields[tag]
|
499
499
|
new_value = field.default_value
|
500
500
|
self.instance_variable_set("@#{field.name}", new_value)
|
501
|
-
if field.
|
501
|
+
if field.kind_of? Field::AggregateField
|
502
502
|
new_value.notify_on_change(self, tag)
|
503
503
|
end
|
504
504
|
@set_fields[tag] = false
|
data/spec/compiler_spec.rb
CHANGED
@@ -4,6 +4,10 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
|
4
4
|
require 'protocol_buffers'
|
5
5
|
require 'protocol_buffers/compiler'
|
6
6
|
|
7
|
+
require 'protocol_buffers/compiler/file_descriptor_to_ruby'
|
8
|
+
|
9
|
+
require 'tmpdir'
|
10
|
+
require 'tempfile'
|
7
11
|
describe ProtocolBuffers, "compiler" do
|
8
12
|
|
9
13
|
test_files = Dir[File.join(File.dirname(__FILE__), "proto_files", "*.proto")]
|
@@ -13,6 +17,8 @@ describe ProtocolBuffers, "compiler" do
|
|
13
17
|
end
|
14
18
|
|
15
19
|
test_files.each do |file|
|
20
|
+
next if File.basename(file) == 'depends.proto'
|
21
|
+
|
16
22
|
it "can compile #{File.basename(file)}" do
|
17
23
|
proc do
|
18
24
|
ProtocolBuffers::Compiler.compile_and_load(file)
|
@@ -20,6 +26,35 @@ describe ProtocolBuffers, "compiler" do
|
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
29
|
+
it 'can compile and instantiate a proto with nested dependencies' do
|
30
|
+
protocfile = Tempfile.new('ruby-protoc')
|
31
|
+
protocfile.binmode
|
32
|
+
|
33
|
+
ProtocolBuffers::Compiler.compile(protocfile.path, %w(
|
34
|
+
spec/proto_files/simple.proto
|
35
|
+
spec/proto_files/nested/child.proto
|
36
|
+
spec/proto_files/depends.proto
|
37
|
+
), :include_dirs => %w(spec/proto_files))
|
38
|
+
|
39
|
+
|
40
|
+
descriptor_set = FileDescriptorSet.parse(protocfile)
|
41
|
+
protocfile.close(true)
|
42
|
+
|
43
|
+
Dir.mktmpdir do |dir|
|
44
|
+
descriptor_set.file.each do |file|
|
45
|
+
name = file.name
|
46
|
+
path = File.join(dir, File.dirname(name), File.basename(name, '.proto') + '.pb.rb')
|
47
|
+
FileUtils.mkdir_p File.dirname(path)
|
48
|
+
File.open(path, "w") {|f|
|
49
|
+
FileDescriptorToRuby.new(file).write(f)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
$LOAD_PATH << dir
|
54
|
+
load File.join(dir, 'depends.pb.rb')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
23
58
|
it "can compile and instantiate a message in a package with under_scores" do
|
24
59
|
Object.send(:remove_const, :UnderScore) if defined?(UnderScore)
|
25
60
|
|
@@ -20,6 +20,9 @@ module Featureful
|
|
20
20
|
class A < ::ProtocolBuffers::Message
|
21
21
|
# forward declarations
|
22
22
|
class Sub < ::ProtocolBuffers::Message; end
|
23
|
+
class Group1 < ::ProtocolBuffers::Message; end
|
24
|
+
class Group2 < ::ProtocolBuffers::Message; end
|
25
|
+
class Group3 < ::ProtocolBuffers::Message; end
|
23
26
|
|
24
27
|
# nested messages
|
25
28
|
class Sub < ::ProtocolBuffers::Message
|
@@ -43,12 +46,54 @@ module Featureful
|
|
43
46
|
optional ::Featureful::A::Sub::SubSub, :subsub1, 3
|
44
47
|
end
|
45
48
|
|
49
|
+
class Group1 < ::ProtocolBuffers::Message
|
50
|
+
# forward declarations
|
51
|
+
class Subgroup < ::ProtocolBuffers::Message; end
|
52
|
+
|
53
|
+
# nested messages
|
54
|
+
class Subgroup < ::ProtocolBuffers::Message
|
55
|
+
required :int32, :i1, 1
|
56
|
+
end
|
57
|
+
|
58
|
+
required :int32, :i1, 1
|
59
|
+
repeated ::Featureful::A::Group1::Subgroup, :subgroup, 2, :group => true
|
60
|
+
end
|
61
|
+
|
62
|
+
class Group2 < ::ProtocolBuffers::Message
|
63
|
+
# forward declarations
|
64
|
+
class Subgroup < ::ProtocolBuffers::Message; end
|
65
|
+
|
66
|
+
# nested messages
|
67
|
+
class Subgroup < ::ProtocolBuffers::Message
|
68
|
+
required :int32, :i1, 1
|
69
|
+
end
|
70
|
+
|
71
|
+
required :int32, :i1, 1
|
72
|
+
repeated ::Featureful::A::Group2::Subgroup, :subgroup, 2, :group => true
|
73
|
+
end
|
74
|
+
|
75
|
+
class Group3 < ::ProtocolBuffers::Message
|
76
|
+
# forward declarations
|
77
|
+
class Subgroup < ::ProtocolBuffers::Message; end
|
78
|
+
|
79
|
+
# nested messages
|
80
|
+
class Subgroup < ::ProtocolBuffers::Message
|
81
|
+
required :int32, :i1, 1
|
82
|
+
end
|
83
|
+
|
84
|
+
required :int32, :i1, 1
|
85
|
+
repeated ::Featureful::A::Group3::Subgroup, :subgroup, 2, :group => true
|
86
|
+
end
|
87
|
+
|
46
88
|
repeated :int32, :i1, 1
|
47
89
|
optional :int32, :i2, 2
|
48
90
|
required :int32, :i3, 3
|
49
91
|
repeated ::Featureful::A::Sub, :sub1, 4
|
50
92
|
optional ::Featureful::A::Sub, :sub2, 5
|
51
93
|
required ::Featureful::A::Sub, :sub3, 6
|
94
|
+
repeated ::Featureful::A::Group1, :group1, 7, :group => true
|
95
|
+
optional ::Featureful::A::Group2, :group2, 8, :group => true
|
96
|
+
required ::Featureful::A::Group3, :group3, 9, :group => true
|
52
97
|
end
|
53
98
|
|
54
99
|
class B < ::ProtocolBuffers::Message
|
@@ -25,6 +25,25 @@ message A {
|
|
25
25
|
repeated Sub sub1 = 4;
|
26
26
|
optional Sub sub2 = 5;
|
27
27
|
required Sub sub3 = 6;
|
28
|
+
|
29
|
+
repeated group Group1 = 7 {
|
30
|
+
required int32 i1 = 1;
|
31
|
+
repeated group Subgroup = 2 {
|
32
|
+
required int32 i1 = 1;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
optional group Group2 = 8 {
|
36
|
+
required int32 i1 = 1;
|
37
|
+
repeated group Subgroup = 2 {
|
38
|
+
required int32 i1 = 1;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
required group Group3 = 9 {
|
42
|
+
required int32 i1 = 1;
|
43
|
+
repeated group Subgroup = 2 {
|
44
|
+
required int32 i1 = 1;
|
45
|
+
}
|
46
|
+
}
|
28
47
|
};
|
29
48
|
|
30
49
|
message B {
|
data/spec/runtime_spec.rb
CHANGED
@@ -135,6 +135,20 @@ describe ProtocolBuffers, "runtime" do
|
|
135
135
|
a1.has_sub2?.should == true
|
136
136
|
end
|
137
137
|
|
138
|
+
it "flags group that have been set" do
|
139
|
+
a1 = Featureful::A.new
|
140
|
+
a1.value_for_tag?(a1.class.field_for_name(:group1).tag).should == true
|
141
|
+
a1.value_for_tag?(a1.class.field_for_name(:group2).tag).should == false
|
142
|
+
a1.value_for_tag?(a1.class.field_for_name(:group3).tag).should == false
|
143
|
+
|
144
|
+
a1.has_group1?.should == true
|
145
|
+
a1.has_group2?.should == false
|
146
|
+
a1.has_group3?.should == false
|
147
|
+
|
148
|
+
a1.group2 = Featureful::A::Group2.new(:i1 => 1)
|
149
|
+
a1.has_group2?.should == true
|
150
|
+
end
|
151
|
+
|
138
152
|
describe "#inspect" do
|
139
153
|
it "should leave out un-set fields" do
|
140
154
|
b1 = Simple::Bar.new
|
@@ -149,6 +163,10 @@ describe ProtocolBuffers, "runtime" do
|
|
149
163
|
a1.has_sub2?.should == false
|
150
164
|
a1.sub2.payload = "ohai"
|
151
165
|
a1.has_sub2?.should == true
|
166
|
+
|
167
|
+
a1.has_group2?.should == false
|
168
|
+
a1.group2.i1 = 1
|
169
|
+
a1.has_sub2?.should == true
|
152
170
|
end
|
153
171
|
|
154
172
|
it "detects changes to a sub-sub-message and flags up the chain" do
|
@@ -609,6 +627,9 @@ describe ProtocolBuffers, "runtime" do
|
|
609
627
|
f.valid?.should == false
|
610
628
|
f.sub3.valid?.should == false
|
611
629
|
f.sub3.payload_type = Featureful::A::Sub::Payloads::P1
|
630
|
+
f.valid?.should == false
|
631
|
+
f.group3.valid?.should == false
|
632
|
+
f.group3.i1 = 1
|
612
633
|
f.valid?.should == true
|
613
634
|
f.sub3.valid?.should == true
|
614
635
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-protocol-buffers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-
|
15
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: autotest-standalone
|
@@ -131,6 +131,7 @@ email:
|
|
131
131
|
- brian@codekitchen.net
|
132
132
|
- bb@xnull.de
|
133
133
|
executables:
|
134
|
+
- protoc-gen-ruby
|
134
135
|
- ruby-protoc
|
135
136
|
extensions: []
|
136
137
|
extra_rdoc_files:
|
@@ -145,6 +146,7 @@ files:
|
|
145
146
|
- LICENSE
|
146
147
|
- README.md
|
147
148
|
- Rakefile
|
149
|
+
- bin/protoc-gen-ruby
|
148
150
|
- bin/ruby-protoc
|
149
151
|
- debian/changelog
|
150
152
|
- debian/compatability
|
@@ -159,6 +161,8 @@ files:
|
|
159
161
|
- lib/protocol_buffers/compiler/descriptor.proto
|
160
162
|
- lib/protocol_buffers/compiler/file_descriptor_to_d.rb
|
161
163
|
- lib/protocol_buffers/compiler/file_descriptor_to_ruby.rb
|
164
|
+
- lib/protocol_buffers/compiler/plugin.pb.rb
|
165
|
+
- lib/protocol_buffers/compiler/plugin.proto
|
162
166
|
- lib/protocol_buffers/limited_io.rb
|
163
167
|
- lib/protocol_buffers/runtime/decoder.rb
|
164
168
|
- lib/protocol_buffers/runtime/encoder.rb
|
@@ -178,6 +182,7 @@ files:
|
|
178
182
|
- spec/proto_files/dotted_package.proto
|
179
183
|
- spec/proto_files/featureful.pb.rb
|
180
184
|
- spec/proto_files/featureful.proto
|
185
|
+
- spec/proto_files/nested/child.proto
|
181
186
|
- spec/proto_files/no_package.proto
|
182
187
|
- spec/proto_files/packed.pb.rb
|
183
188
|
- spec/proto_files/packed.proto
|
@@ -203,12 +208,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
203
208
|
- - ! '>='
|
204
209
|
- !ruby/object:Gem::Version
|
205
210
|
version: '0'
|
211
|
+
segments:
|
212
|
+
- 0
|
213
|
+
hash: 2363751627391486036
|
206
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
215
|
none: false
|
208
216
|
requirements:
|
209
217
|
- - ! '>='
|
210
218
|
- !ruby/object:Gem::Version
|
211
219
|
version: '0'
|
220
|
+
segments:
|
221
|
+
- 0
|
222
|
+
hash: 2363751627391486036
|
212
223
|
requirements: []
|
213
224
|
rubyforge_project:
|
214
225
|
rubygems_version: 1.8.23
|
@@ -224,6 +235,7 @@ test_files:
|
|
224
235
|
- spec/proto_files/dotted_package.proto
|
225
236
|
- spec/proto_files/featureful.pb.rb
|
226
237
|
- spec/proto_files/featureful.proto
|
238
|
+
- spec/proto_files/nested/child.proto
|
227
239
|
- spec/proto_files/no_package.proto
|
228
240
|
- spec/proto_files/packed.pb.rb
|
229
241
|
- spec/proto_files/packed.proto
|