You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by kc...@apache.org on 2008/08/25 23:34:20 UTC

svn commit: r688891 - in /incubator/thrift/trunk/lib/rb: lib/thrift/struct.rb spec/struct_spec.rb

Author: kclark
Date: Mon Aug 25 14:34:19 2008
New Revision: 688891

URL: http://svn.apache.org/viewvc?rev=688891&view=rev
Log:
rb: Speed up Struct#initialize for optional fields [THRFIT-112]

Struct#initialize previously walked over every field and checked for
default values before assigning nil. The new approach assigns defaults
only to fields that have defaults, and lets Ruby handle nil ivars.

Author: Bryan Duxbury

Modified:
    incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb
    incubator/thrift/trunk/lib/rb/spec/struct_spec.rb

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb?rev=688891&r1=688890&r2=688891&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb Mon Aug 25 14:34:19 2008
@@ -4,12 +4,51 @@
 module Thrift
   module Struct
     def initialize(d={})
-      each_field do |fid, type, name, default|
-        value = d.delete(name.to_s) { d.delete(name.to_sym) { default.dup rescue default } }
-        Thrift.check_type(value, struct_fields[fid], name) if Thrift.type_checking
+      # get a copy of the default values to work on, removing defaults in favor of arguments
+      fields_with_defaults = fields_with_default_values.dup
+      d.each_key do |name|
+        fields_with_defaults.delete(name.to_s)
+      end
+      
+      # assign all the user-specified arguments
+      d.each do |name, value|
+        unless name_to_id(name.to_s)
+          raise Exception, "Unknown key given to #{self.class}.new: #{name}"
+        end
+        Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking
         instance_variable_set("@#{name}", value)
       end
-      raise Exception, "Unknown keys given to #{self.class}.new: #{d.keys.join(", ")}" unless d.empty?
+      
+      # assign all the default values
+      fields_with_defaults.each do |name, default_value|
+        instance_variable_set("@#{name}", (default_value.dup rescue default_value))
+      end
+    end
+
+    def fields_with_default_values
+      fields_with_default_values = self.class.instance_variable_get("@fields_with_default_values")
+      unless fields_with_default_values
+        fields_with_default_values = {}
+        struct_fields.each do |fid, field_def|
+          if field_def[:default]
+            fields_with_default_values[field_def[:name]] = field_def[:default]
+          end
+        end
+        self.class.instance_variable_set("@fields_with_default_values", fields_with_default_values)
+      end
+      fields_with_default_values
+    end
+
+    def name_to_id(name)
+      names_to_ids = self.class.instance_variable_get("@names_to_ids")
+      unless names_to_ids
+        names_to_ids = {}
+        struct_fields.each do |fid, field_def|
+          names_to_ids[field_def[:name]] = fid
+        end
+        self.class.instance_variable_set("@names_to_ids", names_to_ids)
+      end
+      names_to_ids[name]
     end
 
     def struct_fields

Modified: incubator/thrift/trunk/lib/rb/spec/struct_spec.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/spec/struct_spec.rb?rev=688891&r1=688890&r2=688891&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/spec/struct_spec.rb (original)
+++ incubator/thrift/trunk/lib/rb/spec/struct_spec.rb Mon Aug 25 14:34:19 2008
@@ -197,8 +197,7 @@
     end
 
     it "should raise an exception when unknown types are given to Thrift::Struct.new" do
-      lambda { Hello.new(:fish => 'salmon') }.should raise_error(Exception, "Unknown keys given to SpecNamespace::Hello.new: fish")
-      lambda { Hello.new(:foo => 'bar', :baz => 'blah', :greeting => 'Good day') }.should raise_error(Exception, /^Unknown keys given to SpecNamespace::Hello.new: (foo, baz|baz, foo)$/)
+      lambda { Hello.new(:fish => 'salmon') }.should raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish")
     end
 
     it "should support `raise Xception, 'message'` for Exception structs" do