From 22909fb9c1e61759f13b69290bbcf1979bf270a6 Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Sun, 7 Feb 2016 19:41:31 -0700 Subject: [PATCH 1/6] add a set of decoding setters for each type that removes the extra copy and starts adding setters by tag so we do not need the get_field lookup when we have a tag --- lib/protobuf/field/base_field.rb | 5 +++++ lib/protobuf/field/bool_field.rb | 14 ++++++++++++++ lib/protobuf/field/bytes_field.rb | 15 +++++++++++++++ lib/protobuf/field/enum_field.rb | 14 ++++++++++++++ lib/protobuf/field/integer_field.rb | 14 ++++++++++++++ lib/protobuf/field/message_field.rb | 4 +--- lib/protobuf/field/string_field.rb | 15 +++++++++++++++ lib/protobuf/field/varint_field.rb | 14 ++++++++++++++ lib/protobuf/message.rb | 3 +-- lib/protobuf/message/serialization.rb | 3 +++ 10 files changed, 96 insertions(+), 5 deletions(-) diff --git a/lib/protobuf/field/base_field.rb b/lib/protobuf/field/base_field.rb index 3ae505a4..5976c1df 100644 --- a/lib/protobuf/field/base_field.rb +++ b/lib/protobuf/field/base_field.rb @@ -176,6 +176,7 @@ def define_accessor else define_getter define_setter + define_decode_setter end end @@ -234,6 +235,10 @@ def define_getter ::Protobuf.field_deprecator.deprecate_method(message_class, method_name) if field.deprecated? end + def define_decode_setter + # empty for now + end + def define_setter field = self method_name = field.setter diff --git a/lib/protobuf/field/bool_field.rb b/lib/protobuf/field/bool_field.rb index 8b4ee651..be6ff88b 100644 --- a/lib/protobuf/field/bool_field.rb +++ b/lib/protobuf/field/bool_field.rb @@ -35,6 +35,20 @@ def decode(value) value == 1 end + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @values[field.name] = field.decode(val) + end + + alias_method tag_method_name, name_method_name + end + end + def encode(value) [value ? 1 : 0].pack('C') end diff --git a/lib/protobuf/field/bytes_field.rb b/lib/protobuf/field/bytes_field.rb index d7f4aee4..9b2888aa 100644 --- a/lib/protobuf/field/bytes_field.rb +++ b/lib/protobuf/field/bytes_field.rb @@ -56,6 +56,21 @@ def wire_type # Private Instance Methods # + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @encode = nil + @values[field.name] = field.decode(val) + end + + alias_method tag_method_name, name_method_name + end + end + def define_setter field = self method_name = field.setter diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb index 71632cde..8d9fec33 100644 --- a/lib/protobuf/field/enum_field.rb +++ b/lib/protobuf/field/enum_field.rb @@ -38,6 +38,20 @@ def enum? # Private Instance Methods # + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @values[field.name] = field.decode(val) + end + + alias_method tag_method_name, name_method_name + end + end + def define_setter field = self message_class.class_eval do diff --git a/lib/protobuf/field/integer_field.rb b/lib/protobuf/field/integer_field.rb index 5eb3b064..2c01994f 100644 --- a/lib/protobuf/field/integer_field.rb +++ b/lib/protobuf/field/integer_field.rb @@ -13,6 +13,20 @@ def decode(value) value end + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @values[field.name] = field.decode(val) + end + + alias_method tag_method_name, name_method_name + end + end + def encode(value) # original Google's library uses 64bits integer for negative value ::Protobuf::Field::VarintField.encode(value & 0xffff_ffff_ffff_ffff) diff --git a/lib/protobuf/field/message_field.rb b/lib/protobuf/field/message_field.rb index 8cb37bd7..938d5b97 100644 --- a/lib/protobuf/field/message_field.rb +++ b/lib/protobuf/field/message_field.rb @@ -17,9 +17,7 @@ def decode(bytes) end def encode(value) - bytes = value.encode - result = ::Protobuf::Field::VarintField.encode(bytes.size) - result << bytes + "#{::Protobuf::Field::VarintField.encode(value.encode.size)}#{value.encode}" end def message? diff --git a/lib/protobuf/field/string_field.rb b/lib/protobuf/field/string_field.rb index ac36ea70..80561d5d 100644 --- a/lib/protobuf/field/string_field.rb +++ b/lib/protobuf/field/string_field.rb @@ -20,6 +20,21 @@ def decode(bytes) bytes_to_decode end + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + val.force_encoding(::Protobuf::Field::StringField::ENCODING) + @values[field.name] = val + end + + alias_method tag_method_name, name_method_name + end + end + def encode(value) value_to_encode = value.dup value_to_encode.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "") diff --git a/lib/protobuf/field/varint_field.rb b/lib/protobuf/field/varint_field.rb index 59fabdcb..dd5143bb 100644 --- a/lib/protobuf/field/varint_field.rb +++ b/lib/protobuf/field/varint_field.rb @@ -63,6 +63,20 @@ def coerce!(val) Integer(val, 10) end + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @values[field.name] = val + end + + alias_method tag_method_name, name_method_name + end + end + def decode(value) value end diff --git a/lib/protobuf/message.rb b/lib/protobuf/message.rb index 9ac1332e..b1274ebd 100644 --- a/lib/protobuf/message.rb +++ b/lib/protobuf/message.rb @@ -77,8 +77,7 @@ def each_field return to_enum(:each_field) unless block_given? self.class.all_fields.each do |field| - value = __send__(field.getter) - yield(field, value) + yield(field, __send__(field.getter)) end end diff --git a/lib/protobuf/message/serialization.rb b/lib/protobuf/message/serialization.rb index 668b6cea..68670bc0 100644 --- a/lib/protobuf/message/serialization.rb +++ b/lib/protobuf/message/serialization.rb @@ -78,6 +78,9 @@ def encode_to(stream) private def set_field_bytes(tag, bytes) + tag_setter_name = "_protobuf_decode_setter_#{tag}" + return __send__(tag_setter_name, bytes) if respond_to?(tag_setter_name) + field = self.class.get_field(tag, true) field.set(self, bytes) if field end From 7637d6009979a87e07887547af87a513cb7bad03 Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Sun, 7 Feb 2016 19:58:27 -0700 Subject: [PATCH 2/6] account for varint types that nee to run through decode and check if field is Integer in enum before going through coerce! routine --- lib/protobuf/field/signed_integer_field.rb | 14 ++++++++++++++ lib/protobuf/field/varint_field.rb | 1 + 2 files changed, 15 insertions(+) diff --git a/lib/protobuf/field/signed_integer_field.rb b/lib/protobuf/field/signed_integer_field.rb index 8945f771..eeccd7ad 100644 --- a/lib/protobuf/field/signed_integer_field.rb +++ b/lib/protobuf/field/signed_integer_field.rb @@ -16,6 +16,20 @@ def decode(value) end end + def define_decode_setter + field = self + name_method_name = "_protobuf_decode_setter_#{field.name}" + tag_method_name = "_protobuf_decode_setter_#{field.tag}" + + message_class.class_eval do + define_method(name_method_name) do |val| + @values[field.name] = field.decode(val) + end + + alias_method tag_method_name, name_method_name + end + end + def encode(value) if value >= 0 VarintField.encode(value << 1) diff --git a/lib/protobuf/field/varint_field.rb b/lib/protobuf/field/varint_field.rb index dd5143bb..f0716d58 100644 --- a/lib/protobuf/field/varint_field.rb +++ b/lib/protobuf/field/varint_field.rb @@ -52,6 +52,7 @@ def self.encode(value, use_cache = true) # def acceptable?(val) + return true if val.is_a?(Integer) && val >= 0 && val < INT32_MAX int_val = coerce!(val) int_val >= self.class.min && int_val <= self.class.max rescue From e06f642a70c2ccdb4632581172822418d42b4301 Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Sun, 7 Feb 2016 20:58:51 -0700 Subject: [PATCH 3/6] do not need to go through field to get the field.name when running the setter --- lib/protobuf/field/base_field.rb | 17 ++++++++++------- lib/protobuf/field/bool_field.rb | 3 ++- lib/protobuf/field/bytes_field.rb | 10 ++++++---- lib/protobuf/field/enum_field.rb | 14 +++++++++----- lib/protobuf/field/integer_field.rb | 3 ++- lib/protobuf/field/message_field.rb | 12 +++++++----- lib/protobuf/field/signed_integer_field.rb | 3 ++- lib/protobuf/field/string_field.rb | 3 ++- lib/protobuf/field/varint_field.rb | 3 ++- 9 files changed, 42 insertions(+), 26 deletions(-) diff --git a/lib/protobuf/field/base_field.rb b/lib/protobuf/field/base_field.rb index 5976c1df..f2b8426a 100644 --- a/lib/protobuf/field/base_field.rb +++ b/lib/protobuf/field/base_field.rb @@ -182,11 +182,12 @@ def define_accessor def define_array_getter field = self + field_name = field.name method_name = field.getter message_class.class_eval do define_method(method_name) do - @values[field.name] ||= ::Protobuf::Field::FieldArray.new(field) + @values[field_name] ||= ::Protobuf::Field::FieldArray.new(field) end end @@ -195,6 +196,7 @@ def define_array_getter def define_array_setter field = self + field_name = field.name method_name = field.setter message_class.class_eval do @@ -206,15 +208,15 @@ def define_array_setter else fail TypeError, <<-TYPE_ERROR Expected repeated value of type '#{field.type_class}' - Got '#{val.class}' for repeated protobuf field #{field.name} + Got '#{val.class}' for repeated protobuf field #{field_name} TYPE_ERROR end if val.nil? || (val.respond_to?(:empty?) && val.empty?) - @values.delete(field.name) + @values.delete(field_name) else - @values[field.name] ||= ::Protobuf::Field::FieldArray.new(field) - @values[field.name].replace(val) + @values[field_name] ||= ::Protobuf::Field::FieldArray.new(field) + @values[field_name].replace(val) end end end @@ -241,15 +243,16 @@ def define_decode_setter def define_setter field = self + field_name = field.name method_name = field.setter message_class.class_eval do define_method(method_name) do |val| @encode = nil if val.nil? || (val.respond_to?(:empty?) && val.empty?) - @values.delete(field.name) + @values.delete(field_name) elsif field.acceptable?(val) - @values[field.name] = field.coerce!(val) + @values[field_name] = field.coerce!(val) else fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}" end diff --git a/lib/protobuf/field/bool_field.rb b/lib/protobuf/field/bool_field.rb index be6ff88b..b45a06b3 100644 --- a/lib/protobuf/field/bool_field.rb +++ b/lib/protobuf/field/bool_field.rb @@ -37,12 +37,13 @@ def decode(value) def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field.name] = field.decode(val) + @values[field_name] = field.decode(val) end alias_method tag_method_name, name_method_name diff --git a/lib/protobuf/field/bytes_field.rb b/lib/protobuf/field/bytes_field.rb index 9b2888aa..961b1c6e 100644 --- a/lib/protobuf/field/bytes_field.rb +++ b/lib/protobuf/field/bytes_field.rb @@ -58,13 +58,14 @@ def wire_type def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| @encode = nil - @values[field.name] = field.decode(val) + @values[field_name] = field.decode(val) end alias_method tag_method_name, name_method_name @@ -73,6 +74,7 @@ def define_decode_setter def define_setter field = self + field_name = field.name method_name = field.setter message_class.class_eval do @@ -80,11 +82,11 @@ def define_setter @encode = nil case val when String, Symbol - @values[field.name] = "#{val}" + @values[field_name] = "#{val}" when NilClass - @values.delete(field.name) + @values.delete(field_name) when ::Protobuf::Message - @values[field.name] = val.dup + @values[field_name] = val.dup else fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}" end diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb index 8d9fec33..d867f78f 100644 --- a/lib/protobuf/field/enum_field.rb +++ b/lib/protobuf/field/enum_field.rb @@ -40,12 +40,13 @@ def enum? def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field.name] = field.decode(val) + @values[field_name] = field.decode(val) end alias_method tag_method_name, name_method_name @@ -54,17 +55,20 @@ def define_decode_setter def define_setter field = self + field_name = field.name + field_type_class = field.type_class + message_class.class_eval do - define_method("#{field.name}=") do |value| + define_method("#{field_name}=") do |value| @encode = nil orig_value = value if value.nil? - @values.delete(field.name) + @values.delete(field_name) else - value = field.type_class.fetch(value) + value = field_type_class.fetch(value) fail TypeError, "Invalid Enum value: #{orig_value.inspect} for #{field.name}" unless value - @values[field.name] = value + @values[field_name] = value end end end diff --git a/lib/protobuf/field/integer_field.rb b/lib/protobuf/field/integer_field.rb index 2c01994f..c9cbd7b2 100644 --- a/lib/protobuf/field/integer_field.rb +++ b/lib/protobuf/field/integer_field.rb @@ -15,12 +15,13 @@ def decode(value) def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field.name] = field.decode(val) + @values[field_name] = field.decode(val) end alias_method tag_method_name, name_method_name diff --git a/lib/protobuf/field/message_field.rb b/lib/protobuf/field/message_field.rb index 938d5b97..e538f30f 100644 --- a/lib/protobuf/field/message_field.rb +++ b/lib/protobuf/field/message_field.rb @@ -36,18 +36,20 @@ def wire_type def define_setter field = self + field_name = field.name + message_class.class_eval do - define_method("#{field.name}=") do |val| + define_method("#{field_name}=") do |val| @encode = nil case when val.nil? - @values.delete(field.name) + @values.delete(field_name) when val.is_a?(field.type_class) - @values[field.name] = val + @values[field_name] = val when val.respond_to?(:to_proto) - @values[field.name] = val.to_proto + @values[field_name] = val.to_proto when val.respond_to?(:to_hash) - @values[field.name] = field.type_class.new(val.to_hash) + @values[field_name] = field.type_class.new(val.to_hash) else fail TypeError, "Expected value of type '#{field.type_class}' for field #{field.name}, but got '#{val.class}'" end diff --git a/lib/protobuf/field/signed_integer_field.rb b/lib/protobuf/field/signed_integer_field.rb index eeccd7ad..9bd47fe8 100644 --- a/lib/protobuf/field/signed_integer_field.rb +++ b/lib/protobuf/field/signed_integer_field.rb @@ -18,12 +18,13 @@ def decode(value) def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field.name] = field.decode(val) + @values[field_name] = field.decode(val) end alias_method tag_method_name, name_method_name diff --git a/lib/protobuf/field/string_field.rb b/lib/protobuf/field/string_field.rb index 80561d5d..089b66b1 100644 --- a/lib/protobuf/field/string_field.rb +++ b/lib/protobuf/field/string_field.rb @@ -22,13 +22,14 @@ def decode(bytes) def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| val.force_encoding(::Protobuf::Field::StringField::ENCODING) - @values[field.name] = val + @values[field_name] = val end alias_method tag_method_name, name_method_name diff --git a/lib/protobuf/field/varint_field.rb b/lib/protobuf/field/varint_field.rb index f0716d58..882b5bc0 100644 --- a/lib/protobuf/field/varint_field.rb +++ b/lib/protobuf/field/varint_field.rb @@ -66,12 +66,13 @@ def coerce!(val) def define_decode_setter field = self + field_name = field.name name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field.name] = val + @values[field_name] = val end alias_method tag_method_name, name_method_name From d096a27f31f9f89583f2ab6472e25668da063c1f Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Sun, 7 Feb 2016 22:15:22 -0700 Subject: [PATCH 4/6] take out nonzero and rewrite VarintPure and use GraphProfile for Jruby --- lib/protobuf/field/integer_field.rb | 2 +- lib/protobuf/field/sfixed32_field.rb | 2 +- lib/protobuf/field/sfixed64_field.rb | 2 +- lib/protobuf/message.rb | 16 +++++++--------- lib/protobuf/varint_pure.rb | 8 ++++---- spec/benchmark/tasks.rb | 2 +- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/protobuf/field/integer_field.rb b/lib/protobuf/field/integer_field.rb index c9cbd7b2..5e1d0cb8 100644 --- a/lib/protobuf/field/integer_field.rb +++ b/lib/protobuf/field/integer_field.rb @@ -9,7 +9,7 @@ class IntegerField < VarintField # def decode(value) - value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero? + value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000) != 0 value end diff --git a/lib/protobuf/field/sfixed32_field.rb b/lib/protobuf/field/sfixed32_field.rb index 9f9b64e9..c8ca1f3a 100644 --- a/lib/protobuf/field/sfixed32_field.rb +++ b/lib/protobuf/field/sfixed32_field.rb @@ -10,7 +10,7 @@ class Sfixed32Field < Int32Field def decode(bytes) value = bytes.unpack('V').first - value -= 0x1_0000_0000 if (value & 0x8000_0000).nonzero? + value -= 0x1_0000_0000 if (value & 0x8000_0000) != 0 value end diff --git a/lib/protobuf/field/sfixed64_field.rb b/lib/protobuf/field/sfixed64_field.rb index fc296483..d7ab755e 100644 --- a/lib/protobuf/field/sfixed64_field.rb +++ b/lib/protobuf/field/sfixed64_field.rb @@ -11,7 +11,7 @@ class Sfixed64Field < Int64Field def decode(bytes) values = bytes.unpack('VV') # 'Q' is machine-dependent, don't use value = values[0] + (values[1] << 32) - value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero? + value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000) != 0 value end diff --git a/lib/protobuf/message.rb b/lib/protobuf/message.rb index b1274ebd..944fc8c4 100644 --- a/lib/protobuf/message.rb +++ b/lib/protobuf/message.rb @@ -83,7 +83,7 @@ def each_field def each_field_for_serialization self.class.all_fields.each do |field| - value = @values[field.getter] + value = @values[field.name] if value.nil? fail ::Protobuf::SerializationError, "Required field #{self.class.name}##{field.name} does not have a value." if field.required? next @@ -145,18 +145,16 @@ def ==(other) end def [](name) - if (field = self.class.get_field(name, true)) - __send__(field.getter) - end + __send__(name) if respond_to?(name) end def []=(name, value) - if (field = self.class.get_field(name, true)) - __send__(field.setter, value) unless value.nil? + setter = "#{name}=" + + if respond_to?(setter) + __send__(setter, value) unless value.nil? else - unless ::Protobuf.ignore_unknown_fields? - fail ::Protobuf::FieldNotDefinedError, name - end + fail ::Protobuf::FieldNotDefinedError, name unless ::Protobuf.ignore_unknown_fields? end end diff --git a/lib/protobuf/varint_pure.rb b/lib/protobuf/varint_pure.rb index eeffbecc..6fe38aad 100644 --- a/lib/protobuf/varint_pure.rb +++ b/lib/protobuf/varint_pure.rb @@ -1,12 +1,12 @@ module Protobuf module VarintPure def decode(stream) - value = index = 0 + value = shift = 0 begin byte = stream.readbyte - value |= (byte & 0x7f) << (7 * index) - index += 1 - end while (byte & 0x80).nonzero? + value |= (byte & 127) << shift + shift += 7 + end while byte > 127 value end end diff --git a/spec/benchmark/tasks.rb b/spec/benchmark/tasks.rb index 631439d6..a98b9683 100644 --- a/spec/benchmark/tasks.rb +++ b/spec/benchmark/tasks.rb @@ -119,7 +119,7 @@ def profile_code(output, &block) when :jruby profile_data = JRuby::Profiler.profile(&block) File.open(output, 'w') do |f| - JRuby::Profiler::FlatProfilePrinter.new(profile_data).printProfile(f) + JRuby::Profiler::GraphProfilePrinter.new(profile_data).printProfile(f) end end end From 481e730c29a281475e660d38060db7a9ce5aae89 Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Mon, 8 Feb 2016 17:26:56 -0700 Subject: [PATCH 5/6] cache type_class when used and make sure we set a valid enum on setter decode --- lib/protobuf/field/bytes_field.rb | 3 ++- lib/protobuf/field/enum_field.rb | 3 ++- lib/protobuf/field/message_field.rb | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/protobuf/field/bytes_field.rb b/lib/protobuf/field/bytes_field.rb index 961b1c6e..0ca8a02f 100644 --- a/lib/protobuf/field/bytes_field.rb +++ b/lib/protobuf/field/bytes_field.rb @@ -75,6 +75,7 @@ def define_decode_setter def define_setter field = self field_name = field.name + field_type_class = field.type_class method_name = field.setter message_class.class_eval do @@ -88,7 +89,7 @@ def define_setter when ::Protobuf::Message @values[field_name] = val.dup else - fail TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}" + fail TypeError, "Unacceptable value #{val} for field #{field_name} of type #{field_type_class}" end end end diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb index d867f78f..da095cef 100644 --- a/lib/protobuf/field/enum_field.rb +++ b/lib/protobuf/field/enum_field.rb @@ -41,12 +41,13 @@ def enum? def define_decode_setter field = self field_name = field.name + field_type_class = field.type_class name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do define_method(name_method_name) do |val| - @values[field_name] = field.decode(val) + @values[field_name] = field_type_class.fetch(val) end alias_method tag_method_name, name_method_name diff --git a/lib/protobuf/field/message_field.rb b/lib/protobuf/field/message_field.rb index e538f30f..c24f8104 100644 --- a/lib/protobuf/field/message_field.rb +++ b/lib/protobuf/field/message_field.rb @@ -37,6 +37,7 @@ def wire_type def define_setter field = self field_name = field.name + field_type_class = field.type_class message_class.class_eval do define_method("#{field_name}=") do |val| @@ -44,14 +45,14 @@ def define_setter case when val.nil? @values.delete(field_name) - when val.is_a?(field.type_class) + when val.is_a?(field_type_class) @values[field_name] = val when val.respond_to?(:to_proto) @values[field_name] = val.to_proto when val.respond_to?(:to_hash) - @values[field_name] = field.type_class.new(val.to_hash) + @values[field_name] = field_type_class.new(val.to_hash) else - fail TypeError, "Expected value of type '#{field.type_class}' for field #{field.name}, but got '#{val.class}'" + fail TypeError, "Expected value of type '#{field_type_class}' for field #{field_name}, but got '#{val.class}'" end end end From 476844f5fd23d234f66c3aecbf45f309b7ae1e00 Mon Sep 17 00:00:00 2001 From: Brandon Dewitt Date: Tue, 9 Feb 2016 12:49:50 -0700 Subject: [PATCH 6/6] remove the name setter for decode as tag is only one needed --- lib/protobuf/field/bool_field.rb | 6 ++---- lib/protobuf/field/bytes_field.rb | 5 +---- lib/protobuf/field/enum_field.rb | 6 ++---- lib/protobuf/field/integer_field.rb | 6 ++---- lib/protobuf/field/signed_integer_field.rb | 6 ++---- lib/protobuf/field/string_field.rb | 6 ++---- lib/protobuf/field/varint_field.rb | 6 ++---- 7 files changed, 13 insertions(+), 28 deletions(-) diff --git a/lib/protobuf/field/bool_field.rb b/lib/protobuf/field/bool_field.rb index 823bac67..4422d93e 100644 --- a/lib/protobuf/field/bool_field.rb +++ b/lib/protobuf/field/bool_field.rb @@ -38,15 +38,13 @@ def decode(value) def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil @values[field_name] = field.decode(val) end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/bytes_field.rb b/lib/protobuf/field/bytes_field.rb index 0ca8a02f..7c61a136 100644 --- a/lib/protobuf/field/bytes_field.rb +++ b/lib/protobuf/field/bytes_field.rb @@ -59,16 +59,13 @@ def wire_type def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| @encode = nil @values[field_name] = field.decode(val) end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb index da095cef..96e13e9e 100644 --- a/lib/protobuf/field/enum_field.rb +++ b/lib/protobuf/field/enum_field.rb @@ -42,15 +42,13 @@ def define_decode_setter field = self field_name = field.name field_type_class = field.type_class - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil @values[field_name] = field_type_class.fetch(val) end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/integer_field.rb b/lib/protobuf/field/integer_field.rb index 5e1d0cb8..254a2a9d 100644 --- a/lib/protobuf/field/integer_field.rb +++ b/lib/protobuf/field/integer_field.rb @@ -16,15 +16,13 @@ def decode(value) def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil @values[field_name] = field.decode(val) end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/signed_integer_field.rb b/lib/protobuf/field/signed_integer_field.rb index 9bd47fe8..44f5730c 100644 --- a/lib/protobuf/field/signed_integer_field.rb +++ b/lib/protobuf/field/signed_integer_field.rb @@ -19,15 +19,13 @@ def decode(value) def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil @values[field_name] = field.decode(val) end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/string_field.rb b/lib/protobuf/field/string_field.rb index 089b66b1..5050daba 100644 --- a/lib/protobuf/field/string_field.rb +++ b/lib/protobuf/field/string_field.rb @@ -23,16 +23,14 @@ def decode(bytes) def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil val.force_encoding(::Protobuf::Field::StringField::ENCODING) @values[field_name] = val end - - alias_method tag_method_name, name_method_name end end diff --git a/lib/protobuf/field/varint_field.rb b/lib/protobuf/field/varint_field.rb index 882b5bc0..9b5ba415 100644 --- a/lib/protobuf/field/varint_field.rb +++ b/lib/protobuf/field/varint_field.rb @@ -67,15 +67,13 @@ def coerce!(val) def define_decode_setter field = self field_name = field.name - name_method_name = "_protobuf_decode_setter_#{field.name}" tag_method_name = "_protobuf_decode_setter_#{field.tag}" message_class.class_eval do - define_method(name_method_name) do |val| + define_method(tag_method_name) do |val| + @encode = nil @values[field_name] = val end - - alias_method tag_method_name, name_method_name end end