ruby-protocol-buffers 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,7 +8,7 @@ class FileDescriptorToRuby < Struct.new(:descriptor)
8
8
 
9
9
  def initialize(descriptor)
10
10
  super
11
- @package_modules = descriptor.package_ ? descriptor.package_.split('.') : []
11
+ @package_modules = descriptor.package ? descriptor.package.split('.') : []
12
12
  @ns = []
13
13
  end
14
14
 
@@ -126,6 +126,12 @@ HEADER
126
126
  if field.default_value && field.default_value != ""
127
127
  fieldline << %{, :default => #{default_value(field)}}
128
128
  end
129
+
130
+ # Dont need to check for 'repeated' attribute or type, protoc will take care of this.
131
+ if field.options.packed
132
+ fieldline << %{, :packed => true }
133
+ end
134
+
129
135
  line fieldline
130
136
  end
131
137
  end
@@ -14,7 +14,7 @@ module ProtocolBuffers
14
14
  wire_type = tag_int & 0b111
15
15
  field = fields[tag]
16
16
 
17
- if field && wire_type != field.wire_type
17
+ if field && ( !( field.packed? || wire_type == field.wire_type ) || ( field.packed? && wire_type != 2 ) )
18
18
  raise(DecodeError, "incorrect wire type for tag: #{field.tag}, expected #{field.wire_type} but got #{wire_type}\n#{field.inspect}")
19
19
  end
20
20
 
@@ -39,7 +39,23 @@ module ProtocolBuffers
39
39
 
40
40
  if field
41
41
  begin
42
- deserialized = field.deserialize(value)
42
+ if field.packed?
43
+ deserialized = []
44
+ until value.eof?
45
+
46
+ decoded = case field.wire_type
47
+ when 0 # VARINT
48
+ Varint.decode(value)
49
+ when 1 # FIXED64
50
+ value.read(8)
51
+ when 5 # FIXED32
52
+ value.read(4)
53
+ end
54
+ deserialized << field.deserialize(decoded)
55
+ end
56
+ else
57
+ deserialized = field.deserialize(value)
58
+ end
43
59
  # merge_field handles repeated field logic
44
60
  message.merge_field(tag, deserialized, field)
45
61
  rescue ArgumentError
@@ -20,8 +20,20 @@ module ProtocolBuffers
20
20
  tag = (field.tag << 3) | wire_type
21
21
 
22
22
  if field.repeated?
23
- value.each { |i| serialize_field(io, tag, wire_type,
24
- field.serialize(i)) }
23
+ next if value.size == 0
24
+
25
+ if field.packed?
26
+ # encode packed field in a LENGTH_DELIMITED wire
27
+ wire_type = 2
28
+ tag = (field.tag << 3) | wire_type
29
+ buf = StringIO.new
30
+ value.each { |i| serialize_field_value(buf, field.wire_type, field.serialize(i)) }
31
+ Varint.encode(io, tag)
32
+ Varint.encode(io, buf.size)
33
+ io.write(buf.string)
34
+ else
35
+ value.each { |i| serialize_field(io, tag, wire_type, field.serialize(i)) }
36
+ end
25
37
  else
26
38
  serialize_field(io, tag, wire_type, field.serialize(value))
27
39
  end
@@ -36,7 +48,10 @@ module ProtocolBuffers
36
48
  def self.serialize_field(io, tag, wire_type, serialized)
37
49
  # write the tag
38
50
  Varint.encode(io, tag)
51
+ self.serialize_field_value(io, wire_type, serialized)
52
+ end
39
53
 
54
+ def self.serialize_field_value(io, wire_type, serialized)
40
55
  # see comment in decoder.rb about magic numbers
41
56
  case wire_type
42
57
  when 0 # VARINT
@@ -97,6 +97,7 @@ module ProtocolBuffers
97
97
  attr_reader :otype, :name, :tag
98
98
 
99
99
  def repeated?; otype == :repeated end
100
+ def packed?; repeated? && @opts[:packed] end
100
101
 
101
102
  def self.create(sender, otype, type, name, tag, opts = {})
102
103
  if type.is_a?(Symbol)
@@ -294,16 +295,26 @@ module ProtocolBuffers
294
295
 
295
296
  def check_value(value)
296
297
  if HAS_ENCODING
297
- value.valid_encoding? || raise(ArgumentError, "string value is not valid utf-8")
298
+ value.dup.force_encoding(Encoding::UTF_8).valid_encoding? || raise(ArgumentError, "string value is not valid utf-8")
299
+ end
300
+ end
301
+
302
+ def serialize(value)
303
+ check_value(value)
304
+ if HAS_ENCODING
305
+ value.dup.force_encoding(Encoding::UTF_8)
306
+ else
307
+ value
298
308
  end
299
309
  end
300
310
 
301
311
  def deserialize(value)
302
312
  read_value = value.read.to_s
303
313
  if HAS_ENCODING
304
- read_value.force_encoding("utf-8")
314
+ read_value.force_encoding(Encoding::UTF_8)
315
+ else
316
+ read_value
305
317
  end
306
- read_value
307
318
  end
308
319
  end
309
320
 
@@ -1,41 +1,41 @@
1
1
  module ProtocolBuffers
2
2
 
3
- module Varint # :nodoc:
4
- # encode/decode methods defined in ext/varint.c
5
-
6
- unless self.respond_to?(:encode)
7
- def self.encode(io, int_val)
8
- if int_val < 0
9
- # negative varints are always encoded with the full 10 bytes
10
- int_val = int_val & 0xffffffff_ffffffff
11
- end
12
- loop do
13
- byte = int_val & 0b0111_1111
14
- int_val >>= 7
15
- if int_val == 0
16
- io << byte.chr
17
- break
18
- else
19
- io << (byte | 0b1000_0000).chr
20
- end
3
+ module VarintPure # :nodoc:
4
+ def encode(io, int_val)
5
+ if int_val < 0
6
+ # negative varints are always encoded with the full 10 bytes
7
+ int_val = int_val & 0xffffffff_ffffffff
8
+ end
9
+ loop do
10
+ byte = int_val & 0b0111_1111
11
+ int_val >>= 7
12
+ if int_val == 0
13
+ io << byte.chr
14
+ break
15
+ else
16
+ io << (byte | 0b1000_0000).chr
21
17
  end
22
18
  end
23
19
  end
24
20
 
25
- unless self.respond_to?(:decode)
26
- def self.decode(io)
27
- int_val = 0
28
- shift = 0
29
- loop do
30
- raise(DecodeError, "too many bytes when decoding varint") if shift >= 64
31
- byte = io.getc.ord
32
- int_val |= (byte & 0b0111_1111) << shift
33
- shift += 7
34
- return int_val if (byte & 0b1000_0000) == 0
35
- end
21
+ def decode(io)
22
+ int_val = 0
23
+ shift = 0
24
+ loop do
25
+ raise(DecodeError, "too many bytes when decoding varint") if shift >= 64
26
+ # this works in 1.8.7 and 1.9.x, but for different reasons
27
+ # in 1.8.7 io.getc returns the int representation of the char, and .ord is a noop. String#ord doesn't exist.
28
+ # in 1.9.3 io.getc returns a String, and .ord returns the int representation of the first char.
29
+ # this fails in 1.8.6, which is no longer supported by ruby-protocol-buffers.
30
+ byte = io.getc.ord
31
+ int_val |= (byte & 0b0111_1111) << shift
32
+ shift += 7
33
+ return int_val if (byte & 0b1000_0000) == 0
36
34
  end
37
35
  end
36
+ end
38
37
 
38
+ class Varint
39
39
  def self.encodeZigZag32(int_val)
40
40
  (int_val << 1) ^ (int_val >> 31)
41
41
  end
@@ -47,16 +47,22 @@ module ProtocolBuffers
47
47
  def self.decodeZigZag32(int_val)
48
48
  (int_val >> 1) ^ -(int_val & 1)
49
49
  end
50
- class << self; alias_method :decodeZigZag64, :decodeZigZag32 end
51
50
 
51
+ class << self
52
+ alias_method :decodeZigZag64, :decodeZigZag32
53
+ end
52
54
  end
53
55
 
54
56
  end
55
57
 
56
- # fix for 1.8 <-> 1.9 compat
57
- unless 'a'.respond_to?(:ord)
58
- class String; def ord; self[0]; end; end
59
- end
60
- unless (1).respond_to?(:ord)
61
- class Fixnum; def ord; self; end; end
58
+ # optionally load C extension
59
+ begin
60
+ require 'varint/varint'
61
+ class ProtocolBuffers::Varint
62
+ extend ::Varint
63
+ end
64
+ rescue LoadError
65
+ class ProtocolBuffers::Varint
66
+ extend ::ProtocolBuffers::VarintPure
67
+ end
62
68
  end
@@ -0,0 +1,3 @@
1
+ module ProtocolBuffers
2
+ VERSION = "1.3.1"
3
+ end
@@ -1,27 +1,28 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "protocol_buffers"
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "protocol_buffers/version"
4
5
 
5
- Gem::Specification.new do |s|
6
- s.name = "ruby-protocol-buffers"
7
- s.version = ProtocolBuffers::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Brian Palmer", "Rob Marable", "Paulo Luis Franchini Casaretto"]
10
- s.email = ["brian@codekitchen.net"]
11
- s.homepage = "https://github.com/mozy/ruby-protocol-buffers"
12
- s.summary = %{Ruby compiler and runtime for the google protocol buffers library.}
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ruby-protocol-buffers"
8
+ gem.version = ProtocolBuffers::VERSION
9
+ gem.authors = ["Brian Palmer", "Benedikt Böhm", "Rob Marable", "Paulo Luis Franchini Casaretto"]
10
+ gem.email = ["brian@codekitchen.net", "bb@xnull.de"]
11
+ gem.summary = %{Ruby compiler and runtime for the google protocol buffers library.}
12
+ gem.homepage = "https://github.com/mozy/ruby-protocol-buffers"
13
13
 
14
- s.files = `git ls-files`.split("\n")
15
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
- s.require_paths = ["lib"]
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
18
 
19
- s.extra_rdoc_files << "Changelog.md"
19
+ gem.extra_rdoc_files << "Changelog.md"
20
20
 
21
- s.add_development_dependency "autotest-standalone"
22
- s.add_development_dependency "autotest-growl"
23
- s.add_development_dependency "rake"
24
- s.add_development_dependency "rcov"
25
- s.add_development_dependency "rspec", "~> 2.5"
26
- s.add_development_dependency "yard"
21
+ gem.add_development_dependency "autotest-standalone"
22
+ gem.add_development_dependency "autotest-growl"
23
+ gem.add_development_dependency "rake"
24
+ gem.add_development_dependency "rake-compiler"
25
+ gem.add_development_dependency "simplecov"
26
+ gem.add_development_dependency "rspec", "~> 2.5"
27
+ gem.add_development_dependency "yard"
27
28
  end
@@ -8,6 +8,10 @@ describe ProtocolBuffers, "compiler" do
8
8
 
9
9
  test_files = Dir[File.join(File.dirname(__FILE__), "proto_files", "*.proto")]
10
10
 
11
+ before do
12
+ pending "need protoc installed" unless has_compiler?
13
+ end
14
+
11
15
  test_files.each do |file|
12
16
  it "can compile #{File.basename(file)}" do
13
17
  proc do
@@ -16,4 +20,22 @@ describe ProtocolBuffers, "compiler" do
16
20
  end
17
21
  end
18
22
 
23
+ it "can compile and instantiate a message in a package with under_scores" do
24
+ Object.send(:remove_const, :UnderScore) if defined?(UnderScore)
25
+
26
+ ProtocolBuffers::Compiler.compile_and_load(
27
+ File.join(File.dirname(__FILE__), "proto_files", "under_score_package.proto"))
28
+
29
+ proc do
30
+ under_test = UnderScore::UnderTest.new
31
+ end.should_not raise_error()
32
+ end
33
+
34
+ it "should compile and correctly translate" do
35
+ ProtocolBuffers::Compiler.compile_and_load(
36
+ File.join(File.dirname(__FILE__), "proto_files", "simple.proto"))
37
+ ProtocolBuffers::Compiler.compile_and_load(
38
+ File.join(File.dirname(__FILE__), "proto_files", "featureful.proto"))
39
+ end
40
+
19
41
  end
data/spec/fields_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # encoding: binary
2
+
1
3
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
4
 
3
5
  require 'stringio'
@@ -36,25 +38,61 @@ describe ProtocolBuffers, "fields" do
36
38
  proc { int64.check_value(int64.deserialize(val2)) }.should_not raise_error
37
39
  end
38
40
 
39
- it "verifies UTF-8 for string fields" do
41
+ context "UTF-8 encoding of length-delimited fields" do
40
42
  if RUBY_VERSION < "1.9"
41
43
  pending "UTF-8 validation only happens in ruby 1.9+"
42
44
  else
43
- good = proc { StringIO.new("hello") }
44
- bad = proc { StringIO.new("\xff\xff") }
45
-
46
- s1 = mkfield(:StringField)
47
- s1.deserialize(good[]).should == "hello"
48
- s1.deserialize(good[]).encoding.should == Encoding.find('utf-8')
49
- proc { s1.check_valid(s1.deserialize(good[])) }.should_not raise_error()
50
- s1.deserialize(bad[]).encoding.should == Encoding.find('utf-8')
51
- proc { s1.check_valid(s1.deserialize(bad[])) }.should raise_error(ArgumentError)
52
-
53
- b1 = mkfield(:BytesField)
54
- b1.deserialize(good[]).should == "hello"
55
- b1.deserialize(good[]).encoding.should == Encoding.find("us-ascii")
56
- b1.deserialize(bad[]).encoding.should == Encoding.find("binary")
57
- proc { b1.check_valid(b1.deserialize(bad[])) }.should_not raise_error()
45
+
46
+ before :each do
47
+ @good_utf = "\xc2\xa1hola\x21"
48
+ @bad_utf = "\xc2"
49
+ @good_ascii = "!hola!".force_encoding("us-ascii")
50
+
51
+ @good_utf_io = proc { StringIO.new(@good_utf) }
52
+ @bad_utf_io = proc { StringIO.new(@bad_utf) }
53
+ @good_ascii_io = proc { StringIO.new(@good_ascii) }
54
+
55
+ @s = mkfield(:StringField)
56
+ @b = mkfield(:BytesField)
57
+ end
58
+
59
+ context "string fields" do
60
+
61
+ it "forces UTF-8 on serializing" do
62
+ @s.serialize(@good_utf).encoding.should == Encoding::UTF_8
63
+ proc { @s.check_valid(@s.serialize(@good_utf)) }.should_not raise_error()
64
+
65
+ @s.serialize(@good_ascii).encoding.should == Encoding::UTF_8
66
+ proc { @s.check_valid(@s.serialize(@good_ascii)) }.should_not raise_error()
67
+
68
+ proc { @s.serialize(@bad_utf) }.should raise_error(ArgumentError)
69
+ end
70
+
71
+ it "forces UTF-8 on deserializing" do
72
+ @s.deserialize(@good_utf_io[]).encoding.should == Encoding::UTF_8
73
+ proc { @s.check_valid(@s.deserialize(@good_utf_io[])) }.should_not raise_error()
74
+
75
+ @s.deserialize(@good_ascii_io[]).encoding.should == Encoding::UTF_8
76
+ proc { @s.check_valid(@s.deserialize(@good_ascii_io[])) }.should_not raise_error()
77
+
78
+ @s.deserialize(@bad_utf_io[]).encoding.should == Encoding::UTF_8
79
+ proc { @s.check_valid(@s.deserialize(@bad_utf_io[])) }.should raise_error(ArgumentError)
80
+ end
81
+ end
82
+
83
+ context "byte fields" do
84
+
85
+ it "does not force UTF-8 on deserializing" do
86
+ @b.deserialize(@good_utf_io[]).encoding.should == Encoding::BINARY
87
+ proc { @b.check_valid(@b.deserialize(@good_utf_io[])) }.should_not raise_error()
88
+
89
+ @b.deserialize(@good_ascii_io[]).encoding.should == Encoding.find("us-ascii")
90
+ proc { @b.check_valid(@b.deserialize(@good_ascii_io[])) }.should_not raise_error()
91
+
92
+ @b.deserialize(@bad_utf_io[]).encoding.should == Encoding::BINARY
93
+ proc { @b.check_valid(@b.deserialize(@bad_utf_io[])) }.should_not raise_error()
94
+ end
95
+ end
58
96
  end
59
97
  end
60
98
 
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+
4
+ require 'protocol_buffers'
5
+
6
+ module Featureful
7
+ # forward declarations
8
+ class A < ::ProtocolBuffers::Message; end
9
+ class B < ::ProtocolBuffers::Message; end
10
+ class ABitOfEverything < ::ProtocolBuffers::Message; end
11
+
12
+ # enums
13
+ module MainPayloads
14
+ include ::ProtocolBuffers::Enum
15
+ P1 = 2
16
+ P2 = 3
17
+ P3 = 4
18
+ end
19
+
20
+ class A < ::ProtocolBuffers::Message
21
+ # forward declarations
22
+ class Sub < ::ProtocolBuffers::Message; end
23
+
24
+ # nested messages
25
+ class Sub < ::ProtocolBuffers::Message
26
+ # forward declarations
27
+ class SubSub < ::ProtocolBuffers::Message; end
28
+
29
+ # enums
30
+ module Payloads
31
+ include ::ProtocolBuffers::Enum
32
+ P1 = 0
33
+ P2 = 1
34
+ end
35
+
36
+ # nested messages
37
+ class SubSub < ::ProtocolBuffers::Message
38
+ optional :string, :subsub_payload, 1
39
+ end
40
+
41
+ optional :string, :payload, 1
42
+ required ::Featureful::A::Sub::Payloads, :payload_type, 2, :default => ::Featureful::A::Sub::Payloads::P1
43
+ optional ::Featureful::A::Sub::SubSub, :subsub1, 3
44
+ end
45
+
46
+ repeated :int32, :i1, 1
47
+ optional :int32, :i2, 2
48
+ required :int32, :i3, 3
49
+ repeated ::Featureful::A::Sub, :sub1, 4
50
+ optional ::Featureful::A::Sub, :sub2, 5
51
+ required ::Featureful::A::Sub, :sub3, 6
52
+ end
53
+
54
+ class B < ::ProtocolBuffers::Message
55
+ repeated ::Featureful::A, :a, 1
56
+ end
57
+
58
+ class ABitOfEverything < ::ProtocolBuffers::Message
59
+ optional :double, :double_field, 1
60
+ optional :float, :float_field, 2
61
+ optional :int32, :int32_field, 3
62
+ optional :int64, :int64_field, 4, :default => 15
63
+ optional :uint32, :uint32_field, 5
64
+ optional :uint64, :uint64_field, 6
65
+ optional :sint32, :sint32_field, 7
66
+ optional :sint64, :sint64_field, 8
67
+ optional :fixed32, :fixed32_field, 9
68
+ optional :fixed64, :fixed64_field, 10
69
+ optional :sfixed32, :sfixed32_field, 11
70
+ optional :sfixed64, :sfixed64_field, 12
71
+ optional :bool, :bool_field, 13, :default => false
72
+ optional :string, :string_field, 14, :default => "zomgkittenz"
73
+ optional :bytes, :bytes_field, 15
74
+ end
75
+
76
+ end