protobuf 3.6.2 → 3.6.6
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.
- 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
|