THRIFT-248. ruby: Factor BinaryProtocolAccelerated into separate protocol and struct components

This patch replaces the "binaryprotocolaccelerated" c extension with the "thrift_native" c extension. This new extension creates native implementations for the struct.rb #write and #read methods, Thrift::BinaryProtocol, and Thrift::MemoryBuffer, but keeps ruby-level interfaces, allowing all protocols to benefit from the struct code and the memory buffer. There is however an additional cost associated with going through this ruby layer, but the increased interoperability seems to be well worth it.

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@739895 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/rb/spec/struct_spec.rb b/lib/rb/spec/struct_spec.rb
index 4dc8714..1a22f57 100644
--- a/lib/rb/spec/struct_spec.rb
+++ b/lib/rb/spec/struct_spec.rb
@@ -1,6 +1,8 @@
 require File.dirname(__FILE__) + '/spec_helper'
 require File.dirname(__FILE__) + '/gen-rb/ThriftSpec_types'
 
+# require "binaryprotocolaccelerated"
+
 class ThriftStructSpec < Spec::ExampleGroup
   include Thrift
   include SpecNamespace
@@ -54,7 +56,7 @@
 
     it "should read itself off the wire" do
       struct = Foo.new
-      prot = mock("Protocol")
+      prot = Protocol.new(mock("transport"))
       prot.should_receive(:read_struct_begin).twice
       prot.should_receive(:read_struct_end).twice
       prot.should_receive(:read_field_begin).and_return(
@@ -79,14 +81,14 @@
       prot.should_receive(:read_list_end)
       prot.should_receive(:read_set_begin).and_return([Types::I16, 2])
       prot.should_receive(:read_set_end)
-      prot.should_receive(:read_type).with(Types::I32).and_return(
+      prot.should_receive(:read_i32).and_return(
         1, 14,        # complex keys
         42,           # simple
         4, 23, 4, 29  # ints
       )
-      prot.should_receive(:read_type).with(Types::STRING).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
-      prot.should_receive(:read_type).with(Types::DOUBLE).and_return(Math::PI, Math::E, 4.669201609)
-      prot.should_receive(:read_type).with(Types::I16).and_return(2, 3)
+      prot.should_receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?")
+      prot.should_receive(:read_double).and_return(Math::PI, Math::E, 4.669201609)
+      prot.should_receive(:read_i16).and_return(2, 3)
       prot.should_not_receive(:skip)
       struct.read(prot)
 
@@ -100,7 +102,7 @@
 
     it "should skip unexpected fields in structs and use default values" do
       struct = Foo.new
-      prot = mock("Protocol")
+      prot = Protocol.new(mock("transport"))
       prot.should_receive(:read_struct_begin)
       prot.should_receive(:read_struct_end)
       prot.should_receive(:read_field_begin).and_return(
@@ -112,10 +114,12 @@
         [nil, Types::STOP, 0]
       )
       prot.should_receive(:read_field_end).exactly(5).times
-      prot.should_receive(:read_type).with(Types::I32).and_return(42)
-      prot.should_receive(:read_type).with(Types::STRING).and_return("foobar")
+      prot.should_receive(:read_i32).and_return(42)
+      prot.should_receive(:read_string).and_return("foobar")
       prot.should_receive(:skip).with(Types::STRUCT)
       prot.should_receive(:skip).with(Types::MAP)
+      # prot.should_receive(:read_map_begin).and_return([Types::I32, Types::I32, 0])
+      # prot.should_receive(:read_map_end)
       prot.should_receive(:skip).with(Types::I32)
       struct.read(prot)
 
@@ -128,31 +132,35 @@
     end
 
     it "should write itself to the wire" do
-      prot = mock("Protocol")
+      prot = Protocol.new(mock("transport")) #mock("Protocol")
       prot.should_receive(:write_struct_begin).with("SpecNamespace::Foo")
-      prot.should_receive(:write_struct_end)
+      prot.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
+      prot.should_receive(:write_struct_end).twice
       prot.should_receive(:write_field_begin).with('ints', Types::LIST, 4)
+      prot.should_receive(:write_i32).with(1)
+      prot.should_receive(:write_i32).with(2).twice
+      prot.should_receive(:write_i32).with(3)
       prot.should_receive(:write_field_begin).with('complex', Types::MAP, 5)
+      prot.should_receive(:write_i32).with(5)
+      prot.should_receive(:write_string).with('foo')
+      prot.should_receive(:write_double).with(1.23)
       prot.should_receive(:write_field_begin).with('shorts', Types::SET, 6)
-      prot.should_receive(:write_field_stop)
-      prot.should_receive(:write_field_end).exactly(3).times
-      prot.should_receive(:write_field).with('simple', Types::I32, 1, 53)
-      prot.should_receive(:write_field).with('hello', Types::STRUCT, 3, Hello.new(:greeting => 'hello, world!'))
+      prot.should_receive(:write_i16).with(5)
+      prot.should_receive(:write_i16).with(17)
+      prot.should_receive(:write_i16).with(239)
+      prot.should_receive(:write_field_stop).twice
+      prot.should_receive(:write_field_end).exactly(6).times
+      prot.should_receive(:write_field_begin).with('simple', Types::I32, 1)
+      prot.should_receive(:write_i32).with(53)
+      prot.should_receive(:write_field_begin).with('hello', Types::STRUCT, 3)
+      prot.should_receive(:write_field_begin).with('greeting', Types::STRING, 1)
+      prot.should_receive(:write_string).with('hello, world!')
       prot.should_receive(:write_map_begin).with(Types::I32, Types::MAP, 1)
       prot.should_receive(:write_map_begin).with(Types::STRING, Types::DOUBLE, 1)
-      prot.should_receive(:write_type).with(Types::I32, 5) # complex/1/key
-      prot.should_receive(:write_type).with(Types::STRING, "foo") # complex/1/value/1/key
-      prot.should_receive(:write_type).with(Types::DOUBLE, 1.23) # complex/1/value/1/value
       prot.should_receive(:write_map_end).twice
       prot.should_receive(:write_list_begin).with(Types::I32, 4)
-      prot.should_receive(:write_type).with(Types::I32, 1)
-      prot.should_receive(:write_type).with(Types::I32, 2).twice
-      prot.should_receive(:write_type).with(Types::I32, 3)
       prot.should_receive(:write_list_end)
       prot.should_receive(:write_set_begin).with(Types::I16, 3)
-      prot.should_receive(:write_type).with(Types::I16, 5)
-      prot.should_receive(:write_type).with(Types::I16, 17)
-      prot.should_receive(:write_type).with(Types::I16, 239)
       prot.should_receive(:write_set_end)
 
       struct = Foo.new
@@ -199,12 +207,15 @@
         e.message.should == "something happened"
         e.code.should == 1
         # ensure it gets serialized properly, this is the really important part
-        prot = mock("Protocol")
+        prot = Protocol.new(mock("trans"))
         prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
         prot.should_receive(:write_struct_end)
-        prot.should_receive(:write_field).with('message', Types::STRING, 1, "something happened")
-        prot.should_receive(:write_field).with('code', Types::I32, 2, 1)
+        prot.should_receive(:write_field_begin).with('message', Types::STRING, 1)#, "something happened")
+        prot.should_receive(:write_string).with("something happened")
+        prot.should_receive(:write_field_begin).with('code', Types::I32, 2)#, 1)
+        prot.should_receive(:write_i32).with(1)
         prot.should_receive(:write_field_stop)
+        prot.should_receive(:write_field_end).twice
 
         e.write(prot)
       end
@@ -216,12 +227,15 @@
       rescue Thrift::Exception => e
         e.message.should == "something happened"
         e.code.should == 5
-        prot = mock("Protocol")
+        prot = Protocol.new(mock("trans"))
         prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
         prot.should_receive(:write_struct_end)
-        prot.should_receive(:write_field).with('message', Types::STRING, 1, "something happened")
-        prot.should_receive(:write_field).with('code', Types::I32, 2, 5)
+        prot.should_receive(:write_field_begin).with('message', Types::STRING, 1)
+        prot.should_receive(:write_string).with("something happened")
+        prot.should_receive(:write_field_begin).with('code', Types::I32, 2)
+        prot.should_receive(:write_i32).with(5)
         prot.should_receive(:write_field_stop)
+        prot.should_receive(:write_field_end).twice
 
         e.write(prot)
       end