protobuf 3.6.2 → 3.6.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/protobuf/decoder.rb +19 -54
- data/lib/protobuf/encoder.rb +13 -58
- data/lib/protobuf/enum.rb +8 -7
- data/lib/protobuf/field/base_field.rb +28 -23
- data/lib/protobuf/field/bool_field.rb +15 -7
- data/lib/protobuf/field/bytes_field.rb +20 -19
- data/lib/protobuf/field/enum_field.rb +1 -0
- data/lib/protobuf/field/message_field.rb +6 -9
- data/lib/protobuf/field/string_field.rb +1 -2
- data/lib/protobuf/field/varint_field.rb +3 -11
- data/lib/protobuf/generators/field_generator.rb +3 -3
- data/lib/protobuf/lifecycle.rb +2 -2
- data/lib/protobuf/message.rb +7 -5
- data/lib/protobuf/message/fields.rb +4 -9
- data/lib/protobuf/message/serialization.rb +6 -4
- data/lib/protobuf/rpc/service_filters.rb +4 -4
- data/lib/protobuf/version.rb +1 -1
- data/spec/benchmark/tasks.rb +4 -2
- data/spec/lib/protobuf/field/bool_field_spec.rb +10 -0
- data/spec/lib/protobuf/message_spec.rb +58 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d7a39cf0258c19f6f58ef3742803720e48db604
|
4
|
+
data.tar.gz: 3f51a132c2a97163934f7ab91b0ac42db9f62d18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4fa8f4ab802085285b5456cdac743e89891cbe0cb0586bcc174ff4cc8f1b6e7eb0297c1b25aa2fc37416b9f9807aa7beca029830582a3ef33fc110e97e3cc6a
|
7
|
+
data.tar.gz: 844d39f70bd8a9cfe47a8051db363a705776f2cd143d5cc437013c1a3d8e5d0be51ca530ccfc311e7ed7b31af76530b4956dde65d563bcbed90adfd9b997ad06
|
data/lib/protobuf/decoder.rb
CHANGED
@@ -5,62 +5,27 @@ module Protobuf
|
|
5
5
|
class Decoder
|
6
6
|
|
7
7
|
# Read bytes from +stream+ and pass to +message+ object.
|
8
|
-
def self.decode_each_field(stream
|
8
|
+
def self.decode_each_field(stream)
|
9
9
|
until stream.eof?
|
10
|
-
|
11
|
-
|
10
|
+
bits = Varint.decode(stream)
|
11
|
+
wire_type = bits & 0x07
|
12
|
+
tag = bits >> 3
|
13
|
+
|
14
|
+
bytes = if wire_type == ::Protobuf::WireType::VARINT
|
15
|
+
Varint.decode(stream)
|
16
|
+
elsif wire_type == ::Protobuf::WireType::LENGTH_DELIMITED
|
17
|
+
value_length = Varint.decode(stream)
|
18
|
+
stream.read(value_length)
|
19
|
+
elsif wire_type == ::Protobuf::WireType::FIXED64
|
20
|
+
stream.read(8)
|
21
|
+
elsif wire_type == ::Protobuf::WireType::FIXED32
|
22
|
+
stream.read(4)
|
23
|
+
else
|
24
|
+
fail InvalidWireType, wire_type
|
25
|
+
end
|
26
|
+
|
27
|
+
yield(tag, bytes)
|
12
28
|
end
|
13
29
|
end
|
14
|
-
|
15
|
-
def self.read_field(stream)
|
16
|
-
tag, wire_type = read_key(stream)
|
17
|
-
bytes = case wire_type
|
18
|
-
when ::Protobuf::WireType::VARINT then
|
19
|
-
Varint.decode(stream)
|
20
|
-
when ::Protobuf::WireType::FIXED64 then
|
21
|
-
read_fixed64(stream)
|
22
|
-
when ::Protobuf::WireType::LENGTH_DELIMITED then
|
23
|
-
read_length_delimited(stream)
|
24
|
-
when ::Protobuf::WireType::FIXED32 then
|
25
|
-
read_fixed32(stream)
|
26
|
-
when ::Protobuf::WireType::START_GROUP then
|
27
|
-
fail NotImplementedError, 'Group is deprecated.'
|
28
|
-
when ::Protobuf::WireType::END_GROUP then
|
29
|
-
fail NotImplementedError, 'Group is deprecated.'
|
30
|
-
else
|
31
|
-
fail InvalidWireType, wire_type
|
32
|
-
end
|
33
|
-
|
34
|
-
[tag, bytes]
|
35
|
-
end
|
36
|
-
|
37
|
-
# Read 32-bit string value from +stream+.
|
38
|
-
def self.read_fixed32(stream)
|
39
|
-
stream.read(4)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Read 64-bit string value from +stream+.
|
43
|
-
def self.read_fixed64(stream)
|
44
|
-
stream.read(8)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Read key pair (tag and wire-type) from +stream+.
|
48
|
-
def self.read_key(stream)
|
49
|
-
bits = read_varint(stream)
|
50
|
-
wire_type = bits & 0x07
|
51
|
-
tag = bits >> 3
|
52
|
-
[tag, wire_type]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Read length-delimited string value from +stream+.
|
56
|
-
def self.read_length_delimited(stream)
|
57
|
-
value_length = read_varint(stream)
|
58
|
-
stream.read(value_length)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Read varint integer value from +stream+.
|
62
|
-
def self.read_varint(stream)
|
63
|
-
Varint.decode(stream)
|
64
|
-
end
|
65
30
|
end
|
66
31
|
end
|
data/lib/protobuf/encoder.rb
CHANGED
@@ -1,67 +1,22 @@
|
|
1
1
|
module Protobuf
|
2
2
|
class Encoder
|
3
|
-
|
4
|
-
def self.encode(stream, message)
|
5
|
-
new(stream, message).encode
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
|
10
|
-
attr_writer :message, :stream
|
11
|
-
|
12
|
-
public
|
13
|
-
|
14
|
-
attr_reader :message, :stream
|
15
|
-
|
16
|
-
def initialize(message, stream)
|
17
|
-
unless message.respond_to?(:each_field_for_serialization)
|
18
|
-
fail ArgumentError, "Message instance must respond to :each_field_for_serialization"
|
19
|
-
end
|
20
|
-
|
21
|
-
self.message = message
|
22
|
-
self.stream = stream
|
23
|
-
end
|
24
|
-
|
25
|
-
def encode
|
3
|
+
def self.encode(message, stream)
|
26
4
|
message.each_field_for_serialization do |field, value|
|
27
|
-
|
5
|
+
if field.repeated?
|
6
|
+
if field.packed?
|
7
|
+
packed_value = value.map { |val| field.encode(val) }.join
|
8
|
+
stream << "#{field.tag_encoded}#{::Protobuf::Field::VarintField.encode(packed_value.size)}#{packed_value}"
|
9
|
+
else
|
10
|
+
value.each do |val|
|
11
|
+
stream << "#{field.tag_encoded}#{field.encode(val)}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
else
|
15
|
+
stream << "#{field.tag_encoded}#{field.encode(value)}"
|
16
|
+
end
|
28
17
|
end
|
29
18
|
|
30
19
|
stream
|
31
20
|
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def encode_field(field, value)
|
36
|
-
if field.repeated?
|
37
|
-
encode_repeated_field(field, value)
|
38
|
-
else
|
39
|
-
write_pair(field, value)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def encode_packed_field(field, value)
|
44
|
-
key = (field.tag << 3) | ::Protobuf::WireType::LENGTH_DELIMITED
|
45
|
-
packed_value = value.map { |val| field.encode(val) }.join
|
46
|
-
stream << ::Protobuf::Field::VarintField.encode(key)
|
47
|
-
stream << ::Protobuf::Field::VarintField.encode(packed_value.size)
|
48
|
-
stream << packed_value
|
49
|
-
end
|
50
|
-
|
51
|
-
def encode_repeated_field(field, value)
|
52
|
-
if field.packed?
|
53
|
-
encode_packed_field(field, value)
|
54
|
-
else
|
55
|
-
value.each { |val| write_pair(field, val) }
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Encode key and value, and write to +stream+.
|
60
|
-
def write_pair(field, value)
|
61
|
-
key = (field.tag << 3) | field.wire_type
|
62
|
-
stream << ::Protobuf::Field::VarintField.encode(key)
|
63
|
-
stream << field.encode(value)
|
64
|
-
end
|
65
|
-
|
66
21
|
end
|
67
22
|
end
|
data/lib/protobuf/enum.rb
CHANGED
@@ -131,8 +131,7 @@ module Protobuf
|
|
131
131
|
# Enums, the first enum defined will be returned.
|
132
132
|
#
|
133
133
|
def self.enum_for_tag(tag)
|
134
|
-
|
135
|
-
value ? value.first : nil
|
134
|
+
(mapped_enums[tag.to_i] || []).first
|
136
135
|
end
|
137
136
|
|
138
137
|
# Public: Get an Enum by a variety of type-checking mechanisms.
|
@@ -156,12 +155,14 @@ module Protobuf
|
|
156
155
|
# Returns an Enum object or nil.
|
157
156
|
#
|
158
157
|
def self.fetch(candidate)
|
158
|
+
return enum_for_tag(candidate) if candidate.is_a?(::Integer)
|
159
|
+
|
159
160
|
case candidate
|
160
|
-
when self
|
161
|
+
when self
|
161
162
|
candidate
|
162
|
-
when ::Numeric
|
163
|
+
when ::Numeric
|
163
164
|
enum_for_tag(candidate.to_i)
|
164
|
-
when ::String, ::Symbol
|
165
|
+
when ::String, ::Symbol
|
165
166
|
enum_for_name(candidate)
|
166
167
|
else
|
167
168
|
nil
|
@@ -280,9 +281,9 @@ module Protobuf
|
|
280
281
|
|
281
282
|
def to_s(format = :tag)
|
282
283
|
case format
|
283
|
-
when :tag
|
284
|
+
when :tag
|
284
285
|
to_i.to_s
|
285
|
-
when :name
|
286
|
+
when :name
|
286
287
|
name.to_s
|
287
288
|
else
|
288
289
|
to_i.to_s
|
@@ -21,7 +21,6 @@ module Protobuf
|
|
21
21
|
##
|
22
22
|
# Attributes
|
23
23
|
#
|
24
|
-
|
25
24
|
attr_reader :message_class, :name, :options, :rule, :tag, :type_class
|
26
25
|
|
27
26
|
##
|
@@ -46,6 +45,7 @@ module Protobuf
|
|
46
45
|
|
47
46
|
validate_packed_field if packed?
|
48
47
|
define_accessor
|
48
|
+
tag_encoded
|
49
49
|
end
|
50
50
|
|
51
51
|
##
|
@@ -70,9 +70,9 @@ module Protobuf
|
|
70
70
|
|
71
71
|
def default_value
|
72
72
|
@default_value ||= case
|
73
|
+
when optional? then typed_default_value
|
73
74
|
when repeated? then ::Protobuf::Field::FieldArray.new(self).freeze
|
74
75
|
when required? then nil
|
75
|
-
when optional? then typed_default_value
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
@@ -122,26 +122,18 @@ module Protobuf
|
|
122
122
|
|
123
123
|
# FIXME: need to cleanup (rename) this warthog of a method.
|
124
124
|
def set(message_instance, bytes)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
else
|
139
|
-
value = decode(bytes)
|
140
|
-
if repeated?
|
141
|
-
message_instance.__send__(getter) << value
|
142
|
-
else
|
143
|
-
message_instance.__send__(setter, value)
|
144
|
-
end
|
125
|
+
return message_instance.__send__(setter, decode(bytes)) unless repeated?
|
126
|
+
return message_instance.__send__(getter) << decode(bytes) unless packed?
|
127
|
+
|
128
|
+
array = message_instance.__send__(getter)
|
129
|
+
stream = StringIO.new(bytes)
|
130
|
+
|
131
|
+
if wire_type == ::Protobuf::WireType::VARINT
|
132
|
+
array << Varint.decode(stream) until stream.eof?
|
133
|
+
elsif wire_type == ::Protobuf::WireType::FIXED64
|
134
|
+
array << stream.read(8) until stream.eof?
|
135
|
+
elsif wire_type == ::Protobuf::WireType::FIXED32
|
136
|
+
array << stream.read(4) until stream.eof?
|
145
137
|
end
|
146
138
|
end
|
147
139
|
|
@@ -149,6 +141,17 @@ module Protobuf
|
|
149
141
|
@setter ||= "#{name}="
|
150
142
|
end
|
151
143
|
|
144
|
+
def tag_encoded
|
145
|
+
@tag_encoded ||= begin
|
146
|
+
case
|
147
|
+
when repeated? && packed?
|
148
|
+
::Protobuf::Field::VarintField.encode((tag << 3) | ::Protobuf::WireType::LENGTH_DELIMITED)
|
149
|
+
else
|
150
|
+
::Protobuf::Field::VarintField.encode((tag << 3) | wire_type)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
152
155
|
# FIXME: add packed, deprecated, extension options to to_s output
|
153
156
|
def to_s
|
154
157
|
"#{rule} #{type_class} #{name} = #{tag} #{default ? "[default=#{default.inspect}]" : ''}"
|
@@ -195,6 +198,7 @@ module Protobuf
|
|
195
198
|
|
196
199
|
message_class.class_eval do
|
197
200
|
define_method(method_name) do |val|
|
201
|
+
@encode = nil
|
198
202
|
if val.is_a?(Array)
|
199
203
|
val = val.dup
|
200
204
|
val.compact!
|
@@ -223,7 +227,7 @@ module Protobuf
|
|
223
227
|
|
224
228
|
message_class.class_eval do
|
225
229
|
define_method(method_name) do
|
226
|
-
@values
|
230
|
+
@values[field.name] || field.default_value
|
227
231
|
end
|
228
232
|
end
|
229
233
|
|
@@ -236,6 +240,7 @@ module Protobuf
|
|
236
240
|
|
237
241
|
message_class.class_eval do
|
238
242
|
define_method(method_name) do |val|
|
243
|
+
@encode = nil
|
239
244
|
if val.nil? || (val.respond_to?(:empty?) && val.empty?)
|
240
245
|
@values.delete(field.name)
|
241
246
|
elsif field.acceptable?(val)
|
@@ -3,6 +3,8 @@ require 'protobuf/field/varint_field'
|
|
3
3
|
module Protobuf
|
4
4
|
module Field
|
5
5
|
class BoolField < VarintField
|
6
|
+
FALSE_STRING = "false".freeze
|
7
|
+
TRUE_STRING = "true".freeze
|
6
8
|
|
7
9
|
##
|
8
10
|
# Class Methods
|
@@ -21,10 +23,9 @@ module Protobuf
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def coerce!(val)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
false
|
26
|
+
case val
|
27
|
+
when String
|
28
|
+
val == TRUE_STRING
|
28
29
|
else
|
29
30
|
val
|
30
31
|
end
|
@@ -45,13 +46,20 @@ module Protobuf
|
|
45
46
|
#
|
46
47
|
|
47
48
|
def define_getter
|
48
|
-
super
|
49
|
-
|
50
49
|
field = self
|
50
|
+
method_name = field.getter
|
51
51
|
|
52
52
|
message_class.class_eval do
|
53
|
-
|
53
|
+
define_method(method_name) do
|
54
|
+
@values.fetch(field.name, field.default_value)
|
55
|
+
end
|
54
56
|
end
|
57
|
+
|
58
|
+
message_class.class_eval do
|
59
|
+
alias_method "#{method_name}?", method_name
|
60
|
+
end
|
61
|
+
|
62
|
+
::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated?
|
55
63
|
end
|
56
64
|
|
57
65
|
end
|
@@ -23,7 +23,7 @@ module Protobuf
|
|
23
23
|
#
|
24
24
|
|
25
25
|
def acceptable?(val)
|
26
|
-
val.
|
26
|
+
val.is_a?(String) || val.nil? || val.is_a?(Symbol) || val.is_a?(::Protobuf::Message)
|
27
27
|
end
|
28
28
|
|
29
29
|
def decode(bytes)
|
@@ -33,12 +33,17 @@ module Protobuf
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def encode(value)
|
36
|
-
value_to_encode =
|
37
|
-
|
38
|
-
|
36
|
+
value_to_encode = ""
|
37
|
+
if value.is_a?(::Protobuf::Message)
|
38
|
+
value_to_encode = value.encode
|
39
|
+
else
|
40
|
+
value_to_encode = value.dup
|
41
|
+
end
|
39
42
|
|
43
|
+
value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
|
40
44
|
string_size = ::Protobuf::Field::VarintField.encode(value_to_encode.size)
|
41
|
-
|
45
|
+
|
46
|
+
"#{string_size}#{value_to_encode}"
|
42
47
|
end
|
43
48
|
|
44
49
|
def wire_type
|
@@ -57,20 +62,16 @@ module Protobuf
|
|
57
62
|
|
58
63
|
message_class.class_eval do
|
59
64
|
define_method(method_name) do |val|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
rescue NoMethodError => ex
|
71
|
-
logger.error { ex.message }
|
72
|
-
logger.error { ex.backtrace.join("\n") }
|
73
|
-
raise TypeError, "Got NoMethodError attempting to set #{val} for field #{field.name} of type #{field.type_class}: #{ex.message}"
|
65
|
+
@encode = nil
|
66
|
+
case val
|
67
|
+
when String, Symbol
|
68
|
+
@values[field.name] = "#{val}"
|
69
|
+
when NilClass
|
70
|
+
@values.delete(field.name)
|
71
|
+
when ::Protobuf::Message
|
72
|
+
@values[field.name] = val.dup
|
73
|
+
else
|
74
|
+
fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}"
|
74
75
|
end
|
75
76
|
end
|
76
77
|
end
|
@@ -9,11 +9,7 @@ module Protobuf
|
|
9
9
|
#
|
10
10
|
|
11
11
|
def acceptable?(val)
|
12
|
-
|
13
|
-
fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'"
|
14
|
-
end
|
15
|
-
|
16
|
-
true
|
12
|
+
val.is_a?(type_class) || val.respond_to?(:to_hash)
|
17
13
|
end
|
18
14
|
|
19
15
|
def decode(bytes)
|
@@ -44,14 +40,15 @@ module Protobuf
|
|
44
40
|
field = self
|
45
41
|
message_class.class_eval do
|
46
42
|
define_method("#{field.name}=") do |val|
|
43
|
+
@encode = nil
|
47
44
|
case
|
48
|
-
when val.nil?
|
45
|
+
when val.nil?
|
49
46
|
@values.delete(field.name)
|
50
|
-
when val.is_a?(field.type_class)
|
47
|
+
when val.is_a?(field.type_class)
|
51
48
|
@values[field.name] = val
|
52
|
-
when val.respond_to?(:to_proto)
|
49
|
+
when val.respond_to?(:to_proto)
|
53
50
|
@values[field.name] = val.to_proto
|
54
|
-
when val.respond_to?(:to_hash)
|
51
|
+
when val.respond_to?(:to_hash)
|
55
52
|
@values[field.name] = field.type_class.new(val.to_hash)
|
56
53
|
else
|
57
54
|
fail TypeError, "Expected value of type '#{field.type_class}' for field #{field.name}, but got '#{val.class}'"
|
@@ -25,8 +25,7 @@ module Protobuf
|
|
25
25
|
value_to_encode.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "")
|
26
26
|
value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
|
27
27
|
|
28
|
-
|
29
|
-
string_size << value_to_encode
|
28
|
+
"#{::Protobuf::Field::VarintField.encode(value_to_encode.size)}#{value_to_encode}"
|
30
29
|
end
|
31
30
|
|
32
31
|
end
|
@@ -8,7 +8,7 @@ module Protobuf
|
|
8
8
|
# Constants
|
9
9
|
#
|
10
10
|
|
11
|
-
CACHE_LIMIT =
|
11
|
+
CACHE_LIMIT = 2048
|
12
12
|
INT32_MAX = 2**31 - 1
|
13
13
|
INT32_MIN = -2**31
|
14
14
|
INT64_MAX = 2**63 - 1
|
@@ -43,7 +43,7 @@ module Protobuf
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# Load the cache of VarInts on load of file
|
46
|
-
(0..CACHE_LIMIT).
|
46
|
+
(0..CACHE_LIMIT).each do |cached_value|
|
47
47
|
cached_varint(cached_value)
|
48
48
|
end
|
49
49
|
|
@@ -68,15 +68,7 @@ module Protobuf
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def encode(value)
|
71
|
-
|
72
|
-
|
73
|
-
bytes = []
|
74
|
-
until value == 0
|
75
|
-
bytes << (0x80 | (value & 0x7f))
|
76
|
-
value >>= 7
|
77
|
-
end
|
78
|
-
bytes[-1] &= 0x7f
|
79
|
-
bytes.pack('C*')
|
71
|
+
::Protobuf::Field::VarintField.encode(value)
|
80
72
|
end
|
81
73
|
|
82
74
|
def wire_type
|
@@ -27,11 +27,11 @@ module Protobuf
|
|
27
27
|
@default_value ||= begin
|
28
28
|
if defaulted?
|
29
29
|
case descriptor.type.name
|
30
|
-
when :TYPE_ENUM
|
30
|
+
when :TYPE_ENUM
|
31
31
|
enum_default_value
|
32
|
-
when :TYPE_STRING, :TYPE_BYTES
|
32
|
+
when :TYPE_STRING, :TYPE_BYTES
|
33
33
|
string_default_value
|
34
|
-
when :TYPE_FLOAT, :TYPE_DOUBLE
|
34
|
+
when :TYPE_FLOAT, :TYPE_DOUBLE
|
35
35
|
float_double_default_value
|
36
36
|
else
|
37
37
|
verbatim_default_value
|
data/lib/protobuf/lifecycle.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Protobuf
|
2
2
|
class Lifecycle
|
3
3
|
class << self
|
4
|
-
def register(event_name
|
4
|
+
def register(event_name)
|
5
5
|
fail "Lifecycle register must have a block" unless block_given?
|
6
6
|
event_name = normalized_event_name(event_name)
|
7
7
|
|
8
8
|
::ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, args|
|
9
|
-
|
9
|
+
yield(*args)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
alias_method :on, :register
|
data/lib/protobuf/message.rb
CHANGED
@@ -40,7 +40,7 @@ module Protobuf
|
|
40
40
|
|
41
41
|
def initialize(fields = {})
|
42
42
|
@values = {}
|
43
|
-
fields.to_hash.
|
43
|
+
fields.to_hash.each do |name, value|
|
44
44
|
self[name] = value
|
45
45
|
end
|
46
46
|
|
@@ -85,8 +85,10 @@ module Protobuf
|
|
85
85
|
def each_field_for_serialization
|
86
86
|
self.class.all_fields.each do |field|
|
87
87
|
value = @values[field.getter]
|
88
|
-
|
89
|
-
|
88
|
+
if value.nil?
|
89
|
+
fail ::Protobuf::SerializationError, "Required field #{self.class.name}##{field.name} does not have a value." if field.required?
|
90
|
+
next
|
91
|
+
end
|
90
92
|
|
91
93
|
yield(field, value)
|
92
94
|
end
|
@@ -118,10 +120,10 @@ module Protobuf
|
|
118
120
|
def to_hash
|
119
121
|
result = {}
|
120
122
|
|
121
|
-
@values.
|
123
|
+
@values.each_key do |field_name|
|
122
124
|
value = __send__(field_name)
|
123
125
|
hashed_value = value.respond_to?(:to_hash_value) ? value.to_hash_value : value
|
124
|
-
result
|
126
|
+
result[field_name] = hashed_value
|
125
127
|
end
|
126
128
|
|
127
129
|
result
|
@@ -78,12 +78,12 @@ module Protobuf
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def get_extension_field(name_or_tag)
|
81
|
-
field = field_store[name_or_tag]
|
81
|
+
field = field_store[name_or_tag]
|
82
82
|
field if field.try(:extension?) { false }
|
83
83
|
end
|
84
84
|
|
85
85
|
def get_field(name_or_tag, allow_extension = false)
|
86
|
-
field = field_store[name_or_tag]
|
86
|
+
field = field_store[name_or_tag]
|
87
87
|
|
88
88
|
if field && (allow_extension || !field.extension?)
|
89
89
|
field
|
@@ -97,14 +97,13 @@ module Protobuf
|
|
97
97
|
raise_if_name_collision(field_name)
|
98
98
|
|
99
99
|
field = ::Protobuf::Field.build(self, rule, type_class, field_name, tag, options)
|
100
|
-
field_store[field_name] = field
|
101
100
|
field_store[tag] = field
|
101
|
+
field_store[field_name] = field
|
102
|
+
field_store[field_name.to_s] = field
|
102
103
|
# defining a new field for the message will cause cached @all_fields, @extension_fields,
|
103
104
|
# and @fields to be incorrect; reset them
|
104
105
|
@all_fields = @extension_fields = @fields = nil
|
105
106
|
|
106
|
-
str_field_store[field_name.to_s] = field
|
107
|
-
|
108
107
|
define_method("#{field_name}!") do
|
109
108
|
@values[field_name]
|
110
109
|
end
|
@@ -129,10 +128,6 @@ module Protobuf
|
|
129
128
|
end
|
130
129
|
private :inherit_fields!
|
131
130
|
|
132
|
-
def str_field_store
|
133
|
-
@str_field_store ||= {}
|
134
|
-
end
|
135
|
-
private :str_field_store
|
136
131
|
end
|
137
132
|
end
|
138
133
|
end
|
@@ -48,10 +48,12 @@ module Protobuf
|
|
48
48
|
# Encode this message
|
49
49
|
#
|
50
50
|
def encode
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
@encode ||= begin
|
52
|
+
stream = ::StringIO.new
|
53
|
+
stream.set_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
|
54
|
+
encode_to(stream)
|
55
|
+
stream.string
|
56
|
+
end
|
55
57
|
end
|
56
58
|
|
57
59
|
# Encode this message to the given stream.
|
@@ -122,7 +122,7 @@ module Protobuf
|
|
122
122
|
def invoke_via_if?(_rpc_method, filter)
|
123
123
|
if_check = filter.fetch(:if) { ->(_service) { return true } }
|
124
124
|
do_invoke = case
|
125
|
-
when if_check.nil?
|
125
|
+
when if_check.nil?
|
126
126
|
true
|
127
127
|
else
|
128
128
|
call_or_send(if_check)
|
@@ -152,7 +152,7 @@ module Protobuf
|
|
152
152
|
def invoke_via_unless?(_rpc_method, filter)
|
153
153
|
unless_check = filter.fetch(:unless) { ->(_service) { return false } }
|
154
154
|
skip_invoke = case
|
155
|
-
when unless_check.nil?
|
155
|
+
when unless_check.nil?
|
156
156
|
false
|
157
157
|
else
|
158
158
|
call_or_send(unless_check)
|
@@ -254,9 +254,9 @@ module Protobuf
|
|
254
254
|
#
|
255
255
|
def call_or_send(callable, *args, &block)
|
256
256
|
return_value = case
|
257
|
-
when callable.respond_to?(:call)
|
257
|
+
when callable.respond_to?(:call)
|
258
258
|
callable.call(self, *args, &block)
|
259
|
-
when respond_to?(callable, true)
|
259
|
+
when respond_to?(callable, true)
|
260
260
|
__send__(callable, *args, &block)
|
261
261
|
else
|
262
262
|
fail "Object #{callable} is not callable"
|
data/lib/protobuf/version.rb
CHANGED
data/spec/benchmark/tasks.rb
CHANGED
@@ -97,7 +97,7 @@ namespace :benchmark do
|
|
97
97
|
args.with_defaults(:number => 1000, :profile_output => "/tmp/profiler_new_#{Time.now.to_i}")
|
98
98
|
create_params = { :name => "The name that we set", :date_created => Time.now.to_i, :status => 2 }
|
99
99
|
profile_code(args[:profile_output]) do
|
100
|
-
Integer(args[:number]).times { Test::Resource.new(create_params).serialize }
|
100
|
+
Integer(args[:number]).times { Test::Resource.decode(Test::Resource.new(create_params).serialize) }
|
101
101
|
end
|
102
102
|
|
103
103
|
puts args[:profile_output]
|
@@ -107,7 +107,9 @@ namespace :benchmark do
|
|
107
107
|
case RUBY_ENGINE.to_sym
|
108
108
|
when :ruby
|
109
109
|
profile_data = RubyProf.profile(&block)
|
110
|
-
|
110
|
+
::File.open(output, "w") do |output_file|
|
111
|
+
RubyProf::FlatPrinter.new(profile_data).print(output_file)
|
112
|
+
end
|
111
113
|
when :rbx
|
112
114
|
profiler = Rubinius::Profiler::Instrumenter.new
|
113
115
|
profiler.profile(false, &block)
|
@@ -4,6 +4,7 @@ RSpec.describe Protobuf::Field::Int32Field do
|
|
4
4
|
|
5
5
|
class SomeBoolMessage < ::Protobuf::Message
|
6
6
|
optional :bool, :some_bool, 1
|
7
|
+
required :bool, :required_bool, 2
|
7
8
|
end
|
8
9
|
|
9
10
|
let(:instance) { SomeBoolMessage.new }
|
@@ -48,4 +49,13 @@ RSpec.describe Protobuf::Field::Int32Field do
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
52
|
+
describe '#define_getter' do
|
53
|
+
context 'when required bool field is set to false' do
|
54
|
+
subject { instance.required_bool = false; instance.required_bool }
|
55
|
+
|
56
|
+
it 'returns false' do
|
57
|
+
expect(subject).to eq(false)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
51
61
|
end
|
@@ -268,6 +268,64 @@ RSpec.describe Protobuf::Message do
|
|
268
268
|
end
|
269
269
|
end
|
270
270
|
|
271
|
+
describe 'memoization' do
|
272
|
+
it "should memoize enum message" do
|
273
|
+
test_enum = Test::EnumTestMessage.new
|
274
|
+
test_enum.encode
|
275
|
+
expect(test_enum.instance_variable_get(:@encode)).to eq("")
|
276
|
+
test_enum.non_default_enum = 2
|
277
|
+
expect(test_enum.instance_variable_get(:@encode)).to be_nil
|
278
|
+
end
|
279
|
+
|
280
|
+
context "boolean fields" do
|
281
|
+
let(:values) { { :ext_is_searchable => true, :name => "STEPH CURRY" } }
|
282
|
+
let(:test_resource) { ::Test::Resource.new(values) }
|
283
|
+
|
284
|
+
it "should memoize after bool values change " do
|
285
|
+
test_resource.encode
|
286
|
+
expect(test_resource.instance_variable_get(:@encode)).to eq(test_resource.encode)
|
287
|
+
test_resource.ext_is_searchable = false
|
288
|
+
expect(test_resource.instance_variable_get(:@encode)).to be_nil
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context "string" do
|
293
|
+
let(:values) { { :ext_is_searchable => true, :name => "STEPH CURRY" } }
|
294
|
+
let(:test_resource) { ::Test::Resource.new(values) }
|
295
|
+
|
296
|
+
it "should memoize after bool values change " do
|
297
|
+
test_resource.encode
|
298
|
+
expect(test_resource.instance_variable_get(:@encode)).to eq(test_resource.encode)
|
299
|
+
test_resource.name = "MVP"
|
300
|
+
expect(test_resource.instance_variable_get(:@encode)).to be_nil
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "string" do
|
305
|
+
let(:values) { { :ext_is_searchable => true, :name => "STEPH CURRY" } }
|
306
|
+
let(:test_resource) { ::Test::Resource.new(values) }
|
307
|
+
|
308
|
+
it "should memoize after string values change " do
|
309
|
+
test_resource.encode
|
310
|
+
expect(test_resource.instance_variable_get(:@encode)).to eq(test_resource.encode)
|
311
|
+
test_resource.name = "MVP"
|
312
|
+
expect(test_resource.instance_variable_get(:@encode)).to be_nil
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "Int64" do
|
317
|
+
let(:values) { { :name => "STEPH CURRY", :date_created => 1454712125 } }
|
318
|
+
let(:test_resource) { ::Test::Resource.new(values) }
|
319
|
+
|
320
|
+
it "should memoize after Int64 values change " do
|
321
|
+
test_resource.encode
|
322
|
+
expect(test_resource.instance_variable_get(:@encode)).to eq(test_resource.encode)
|
323
|
+
test_resource.date_created = 5554712127
|
324
|
+
expect(test_resource.instance_variable_get(:@encode)).to be_nil
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
271
329
|
context "when there's no value for a required field" do
|
272
330
|
let(:message) { ::Test::ResourceWithRequiredField.new }
|
273
331
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protobuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.6.
|
4
|
+
version: 3.6.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BJ Neilsen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-02-
|
14
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|