You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by br...@apache.org on 2009/02/02 01:48:17 UTC

svn commit: r739895 [1/2] - in /incubator/thrift/trunk/lib/rb: ./ ext/ lib/thrift/ lib/thrift/protocol/ spec/

Author: bryanduxbury
Date: Mon Feb  2 00:48:17 2009
New Revision: 739895

URL: http://svn.apache.org/viewvc?rev=739895&view=rev
Log:
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.

Added:
    incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.c
    incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.h
    incubator/thrift/trunk/lib/rb/ext/constants.h
    incubator/thrift/trunk/lib/rb/ext/memory_buffer.c
    incubator/thrift/trunk/lib/rb/ext/memory_buffer.h
    incubator/thrift/trunk/lib/rb/ext/protocol.c
    incubator/thrift/trunk/lib/rb/ext/protocol.h
    incubator/thrift/trunk/lib/rb/ext/struct.c
    incubator/thrift/trunk/lib/rb/ext/struct.h
    incubator/thrift/trunk/lib/rb/ext/thrift_native.c
Removed:
    incubator/thrift/trunk/lib/rb/ext/binaryprotocolaccelerated.c
Modified:
    incubator/thrift/trunk/lib/rb/Manifest
    incubator/thrift/trunk/lib/rb/ext/extconf.rb
    incubator/thrift/trunk/lib/rb/lib/thrift/protocol.rb
    incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocol.rb
    incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocolaccelerated.rb
    incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb
    incubator/thrift/trunk/lib/rb/lib/thrift/thrift.rb
    incubator/thrift/trunk/lib/rb/spec/binaryprotocol_spec_shared.rb
    incubator/thrift/trunk/lib/rb/spec/binaryprotocolaccelerated_spec.rb
    incubator/thrift/trunk/lib/rb/spec/protocol_spec.rb
    incubator/thrift/trunk/lib/rb/spec/serializer_spec.rb
    incubator/thrift/trunk/lib/rb/spec/spec_helper.rb
    incubator/thrift/trunk/lib/rb/spec/struct_spec.rb

Modified: incubator/thrift/trunk/lib/rb/Manifest
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/Manifest?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/Manifest (original)
+++ incubator/thrift/trunk/lib/rb/Manifest Mon Feb  2 00:48:17 2009
@@ -8,7 +8,18 @@
 benchmark/thin_server.rb
 CHANGELOG
 COPYING
-ext/binaryprotocolaccelerated.c
+ext/binary_protocol_accelerated.c
+ext/binary_protocol_accelerated.h
+ext/struct.c
+ext/struct.h
+ext/protocol.h
+ext/protocol.c
+ext/constants.h
+ext/memory_buffer.h
+ext/memory_buffer.c
+ext/rope_transport.c
+ext/rope_transport.h
+ext/thrift_native.c
 ext/extconf.rb
 lib/thrift/client.rb
 lib/thrift/deprecation.rb

Added: incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.c
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.c?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.c (added)
+++ incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.c Mon Feb  2 00:48:17 2009
@@ -0,0 +1,437 @@
+#include <ruby.h>
+#include <stdbool.h>
+#include <constants.h>
+#include <struct.h>
+
+#define GET_TRANSPORT(obj) rb_ivar_get(obj, transport_ivar_id)
+#define WRITE(obj, data, length) rb_funcall(obj, write_method_id, 1, rb_str_new(data, length))
+#define CHECK_NIL(obj) if (NIL_P(obj)) { rb_raise(rb_eStandardError, "nil argument not allowed!");}
+
+VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
+  return Qtrue;
+}
+
+
+
+static int VERSION_1;
+static int VERSION_MASK;
+static int BAD_VERSION;
+
+static void write_byte_direct(VALUE trans, int8_t b) {
+  WRITE(trans, (char*)&b, 1);
+}
+
+static void write_i16_direct(VALUE trans, int16_t value) {
+  char data[2];
+  
+  data[1] = value;
+  data[0] = (value >> 8);
+
+  WRITE(trans, data, 2);
+}
+
+static void write_i32_direct(VALUE trans, int32_t value) {
+  char data[4];
+
+  data[3] = value;
+  data[2] = (value >> 8);
+  data[1] = (value >> 16);
+  data[0] = (value >> 24);
+
+  WRITE(trans, data, 4);
+}
+
+
+static void write_i64_direct(VALUE trans, int64_t value) {
+  char data[8];
+
+  data[7] = value;
+  data[6] = (value >> 8);
+  data[5] = (value >> 16);
+  data[4] = (value >> 24);
+  data[3] = (value >> 32);
+  data[2] = (value >> 40);
+  data[1] = (value >> 48);
+  data[0] = (value >> 56);
+
+  WRITE(trans, data, 8);
+}
+
+static void write_string_direct(VALUE trans, VALUE str) {
+  write_i32_direct(trans, RSTRING(str)->len);
+  rb_funcall(trans, write_method_id, 1, str);
+}
+
+//--------------------------------
+// interface writing methods
+//--------------------------------
+
+VALUE rb_thrift_binary_proto_write_message_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_struct_begin(VALUE self, VALUE name) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_struct_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_field_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_map_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_list_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_set_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) {
+  VALUE trans = GET_TRANSPORT(self);
+  write_i32_direct(trans, VERSION_1 | FIX2INT(type));
+  write_string_direct(trans, name);
+  write_i32_direct(trans, FIX2INT(seqid));
+  
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
+  VALUE trans = GET_TRANSPORT(self);
+  write_byte_direct(trans, FIX2INT(type));
+  write_i16_direct(trans, FIX2INT(id));
+  
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) {
+  write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP);
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) {
+  VALUE trans = GET_TRANSPORT(self);
+  write_byte_direct(trans, FIX2INT(ktype));
+  write_byte_direct(trans, FIX2INT(vtype));
+  write_i32_direct(trans, FIX2INT(size));
+  
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) {
+  VALUE trans = GET_TRANSPORT(self);
+  write_byte_direct(trans, FIX2INT(etype));
+  write_i32_direct(trans, FIX2INT(size));
+  
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) {
+  rb_thrift_binary_proto_write_list_begin(self, etype, size);
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) {
+  write_byte_direct(GET_TRANSPORT(self), RTEST(b) ? 1 : 0);
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) {
+  CHECK_NIL(byte);
+  write_byte_direct(GET_TRANSPORT(self), NUM2INT(byte));
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) {
+  CHECK_NIL(i16);
+  write_i16_direct(GET_TRANSPORT(self), FIX2INT(i16));
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) {
+  CHECK_NIL(i32);
+  write_i32_direct(GET_TRANSPORT(self), NUM2INT(i32));
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) {
+  CHECK_NIL(i64);
+  write_i64_direct(GET_TRANSPORT(self), NUM2LL(i64));
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_double(VALUE self, VALUE dub) {
+  CHECK_NIL(dub);
+  // Unfortunately, bitwise_cast doesn't work in C.  Bad C!
+  union {
+    double f;
+    int64_t t;
+  } transfer;
+  transfer.f = RFLOAT(rb_Float(dub))->value;
+  write_i64_direct(GET_TRANSPORT(self), transfer.t);
+
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_write_string(VALUE self, VALUE str) {
+  CHECK_NIL(str);
+  VALUE trans = GET_TRANSPORT(self);
+  // write_i32_direct(trans, RSTRING(str)->len);
+  // rb_funcall(trans, write_method_id, 1, str);
+  write_string_direct(trans, str);
+  return Qnil;
+}
+
+//---------------------------------------
+// interface reading methods
+//---------------------------------------
+
+#define READ(obj, length) rb_funcall(GET_TRANSPORT(obj), read_method_id, 1, INT2FIX(length)) 
+
+VALUE rb_thrift_binary_proto_read_string(VALUE self);
+VALUE rb_thrift_binary_proto_read_byte(VALUE self);
+VALUE rb_thrift_binary_proto_read_i32(VALUE self);
+VALUE rb_thrift_binary_proto_read_i16(VALUE self);
+
+static char read_byte_direct(VALUE self) {
+  return (RSTRING(READ(self, 1))->ptr)[0];
+}
+
+static int16_t read_i16_direct(VALUE self) {
+  VALUE buf = READ(self, 2);
+  return (int16_t)(((uint8_t)(RSTRING(buf)->ptr[1])) | ((uint16_t)((RSTRING(buf)->ptr[0]) << 8)));
+}
+
+static int32_t read_i32_direct(VALUE self) {
+  VALUE buf = READ(self, 4);
+  return ((uint8_t)(RSTRING(buf)->ptr[3])) | 
+    (((uint8_t)(RSTRING(buf)->ptr[2])) << 8) | 
+    (((uint8_t)(RSTRING(buf)->ptr[1])) << 16) | 
+    (((uint8_t)(RSTRING(buf)->ptr[0])) << 24);
+}
+
+static int64_t read_i64_direct(VALUE self) {
+  uint64_t hi = read_i32_direct(self);
+  uint32_t lo = read_i32_direct(self);
+  return (hi << 32) | lo;
+}
+
+static VALUE get_protocol_exception(VALUE code, VALUE message) {
+  VALUE args[2];
+  args[0] = code;
+  args[1] = message;
+  return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
+}
+
+VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_struct_begin(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_struct_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_field_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_map_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_list_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_binary_proto_read_set_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
+  int version = read_i32_direct(self);
+  if ((version & VERSION_MASK) != VERSION_1) {
+    rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier")));
+  }
+  
+  int type = version & 0x000000ff;
+  VALUE name = rb_thrift_binary_proto_read_string(self);
+  VALUE seqid = rb_thrift_binary_proto_read_i32(self);
+  
+  return rb_ary_new3(3, name, INT2FIX(type), seqid);
+}
+
+VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) {
+  int type = read_byte_direct(self);
+  if (type == TTYPE_STOP) {
+    return rb_ary_new3(3, Qnil, INT2FIX(type), INT2FIX(0));
+  } else {
+    VALUE id = rb_thrift_binary_proto_read_i16(self);
+    return rb_ary_new3(3, Qnil, INT2FIX(type), id);
+  }
+}
+
+VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) {
+  VALUE ktype = rb_thrift_binary_proto_read_byte(self);
+  VALUE vtype = rb_thrift_binary_proto_read_byte(self);
+  VALUE size = rb_thrift_binary_proto_read_i32(self);
+  return rb_ary_new3(3, ktype, vtype, size);
+}
+
+VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) {
+  VALUE etype = rb_thrift_binary_proto_read_byte(self);
+  VALUE size = rb_thrift_binary_proto_read_i32(self);
+  return rb_ary_new3(2, etype, size);
+}
+
+VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) {
+  return rb_thrift_binary_proto_read_list_begin(self);
+}
+
+VALUE rb_thrift_binary_proto_read_bool(VALUE self) {
+  char byte = read_byte_direct(self);
+  return byte == 1 ? Qtrue : Qfalse;
+}
+
+VALUE rb_thrift_binary_proto_read_byte(VALUE self) {
+  return INT2FIX(read_byte_direct(self));
+}
+
+VALUE rb_thrift_binary_proto_read_i16(VALUE self) {
+  return INT2FIX(read_i16_direct(self));
+}
+
+VALUE rb_thrift_binary_proto_read_i32(VALUE self) {
+  return INT2NUM(read_i32_direct(self));
+}
+
+VALUE rb_thrift_binary_proto_read_i64(VALUE self) {
+  return LL2NUM(read_i64_direct(self));
+}
+
+VALUE rb_thrift_binary_proto_read_double(VALUE self) {
+  union {
+    double f;
+    int64_t t;
+  } transfer;
+  transfer.t = read_i64_direct(self);
+  return rb_float_new(transfer.f);
+}
+
+VALUE rb_thrift_binary_proto_read_string(VALUE self) {
+  int size = read_i32_direct(self);
+  return READ(self, size);
+}
+
+void Init_binary_protocol_accelerated() {
+  VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol"));
+  
+  VERSION_1 = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1")));
+  VERSION_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_MASK")));
+  
+  VALUE bpa_class = rb_define_class_under(thrift_module, "BinaryProtocolAccelerated", thrift_binary_protocol_class);
+  
+  rb_define_method(bpa_class, "native?", rb_thrift_binary_proto_native_qmark, 0);
+  
+  rb_define_method(bpa_class, "write_message_begin", rb_thrift_binary_proto_write_message_begin, 3);
+  rb_define_method(bpa_class, "write_field_begin",   rb_thrift_binary_proto_write_field_begin, 3);
+  rb_define_method(bpa_class, "write_field_stop",    rb_thrift_binary_proto_write_field_stop, 0);
+  rb_define_method(bpa_class, "write_map_begin",     rb_thrift_binary_proto_write_map_begin, 3);
+  rb_define_method(bpa_class, "write_list_begin",    rb_thrift_binary_proto_write_list_begin, 2);
+  rb_define_method(bpa_class, "write_set_begin",     rb_thrift_binary_proto_write_set_begin, 2);
+  rb_define_method(bpa_class, "write_byte",          rb_thrift_binary_proto_write_byte, 1);
+  rb_define_method(bpa_class, "write_bool",          rb_thrift_binary_proto_write_bool, 1);
+  rb_define_method(bpa_class, "write_i16",           rb_thrift_binary_proto_write_i16, 1);
+  rb_define_method(bpa_class, "write_i32",           rb_thrift_binary_proto_write_i32, 1);
+  rb_define_method(bpa_class, "write_i64",           rb_thrift_binary_proto_write_i64, 1);
+  rb_define_method(bpa_class, "write_double",        rb_thrift_binary_proto_write_double, 1);
+  rb_define_method(bpa_class, "write_string",        rb_thrift_binary_proto_write_string, 1);
+  // unused methods
+  rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0);
+  rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1);
+  rb_define_method(bpa_class, "write_struct_end", rb_thrift_binary_proto_write_struct_end, 0);
+  rb_define_method(bpa_class, "write_field_end", rb_thrift_binary_proto_write_field_end, 0);
+  rb_define_method(bpa_class, "write_map_end", rb_thrift_binary_proto_write_map_end, 0);
+  rb_define_method(bpa_class, "write_list_end", rb_thrift_binary_proto_write_list_end, 0);
+  rb_define_method(bpa_class, "write_set_end", rb_thrift_binary_proto_write_set_end, 0);
+  
+
+
+  rb_define_method(bpa_class, "read_message_begin",  rb_thrift_binary_proto_read_message_begin, 0);
+  rb_define_method(bpa_class, "read_field_begin",    rb_thrift_binary_proto_read_field_begin, 0);
+  rb_define_method(bpa_class, "read_map_begin",      rb_thrift_binary_proto_read_map_begin, 0);
+  rb_define_method(bpa_class, "read_list_begin",     rb_thrift_binary_proto_read_list_begin, 0);
+  rb_define_method(bpa_class, "read_set_begin",      rb_thrift_binary_proto_read_set_begin, 0);
+  rb_define_method(bpa_class, "read_byte",           rb_thrift_binary_proto_read_byte, 0);
+  rb_define_method(bpa_class, "read_bool",           rb_thrift_binary_proto_read_bool, 0);
+  rb_define_method(bpa_class, "read_i16",            rb_thrift_binary_proto_read_i16, 0);
+  rb_define_method(bpa_class, "read_i32",            rb_thrift_binary_proto_read_i32, 0);
+  rb_define_method(bpa_class, "read_i64",            rb_thrift_binary_proto_read_i64, 0);
+  rb_define_method(bpa_class, "read_double",         rb_thrift_binary_proto_read_double, 0);
+  rb_define_method(bpa_class, "read_string",         rb_thrift_binary_proto_read_string, 0);
+  // unused methods
+  rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0);
+  rb_define_method(bpa_class, "read_struct_begin", rb_thift_binary_proto_read_struct_begin, 0);
+  rb_define_method(bpa_class, "read_struct_end", rb_thift_binary_proto_read_struct_end, 0);
+  rb_define_method(bpa_class, "read_field_end", rb_thift_binary_proto_read_field_end, 0);
+  rb_define_method(bpa_class, "read_map_end", rb_thift_binary_proto_read_map_end, 0);
+  rb_define_method(bpa_class, "read_list_end", rb_thift_binary_proto_read_list_end, 0);
+  rb_define_method(bpa_class, "read_set_end", rb_thift_binary_proto_read_set_end, 0);
+
+  // set up native method table
+  native_proto_method_table *npmt;
+  npmt = ALLOC(native_proto_method_table);
+
+  npmt->write_field_begin = rb_thrift_binary_proto_write_field_begin;
+  npmt->write_field_stop = rb_thrift_binary_proto_write_field_stop;
+  npmt->write_map_begin = rb_thrift_binary_proto_write_map_begin;
+  npmt->write_list_begin = rb_thrift_binary_proto_write_list_begin;
+  npmt->write_set_begin = rb_thrift_binary_proto_write_set_begin;
+  npmt->write_byte = rb_thrift_binary_proto_write_byte;
+  npmt->write_bool = rb_thrift_binary_proto_write_bool;
+  npmt->write_i16 = rb_thrift_binary_proto_write_i16;
+  npmt->write_i32 = rb_thrift_binary_proto_write_i32;
+  npmt->write_i64 = rb_thrift_binary_proto_write_i64;
+  npmt->write_double = rb_thrift_binary_proto_write_double;
+  npmt->write_string = rb_thrift_binary_proto_write_string;
+  npmt->write_message_end = rb_thrift_binary_proto_write_message_end;
+  npmt->write_struct_begin = rb_thrift_binary_proto_write_struct_begin;
+  npmt->write_struct_end = rb_thrift_binary_proto_write_struct_end;
+  npmt->write_field_end = rb_thrift_binary_proto_write_field_end;
+  npmt->write_map_end = rb_thrift_binary_proto_write_map_end;
+  npmt->write_list_end = rb_thrift_binary_proto_write_list_end;
+  npmt->write_set_end = rb_thrift_binary_proto_write_set_end;
+
+  npmt->read_message_begin = rb_thrift_binary_proto_read_message_begin;
+  npmt->read_field_begin = rb_thrift_binary_proto_read_field_begin;
+  npmt->read_map_begin = rb_thrift_binary_proto_read_map_begin;
+  npmt->read_list_begin = rb_thrift_binary_proto_read_list_begin;
+  npmt->read_set_begin = rb_thrift_binary_proto_read_set_begin;
+  npmt->read_byte = rb_thrift_binary_proto_read_byte;
+  npmt->read_bool = rb_thrift_binary_proto_read_bool;
+  npmt->read_i16 = rb_thrift_binary_proto_read_i16;
+  npmt->read_i32 = rb_thrift_binary_proto_read_i32;
+  npmt->read_i64 = rb_thrift_binary_proto_read_i64;
+  npmt->read_double = rb_thrift_binary_proto_read_double;
+  npmt->read_string = rb_thrift_binary_proto_read_string;
+  npmt->read_message_end = rb_thrift_binary_proto_read_message_end;
+  npmt->read_struct_begin = rb_thift_binary_proto_read_struct_begin;
+  npmt->read_struct_end = rb_thift_binary_proto_read_struct_end;
+  npmt->read_field_end = rb_thift_binary_proto_read_field_end;
+  npmt->read_map_end = rb_thift_binary_proto_read_map_end;
+  npmt->read_list_end = rb_thift_binary_proto_read_list_end;
+  npmt->read_set_end = rb_thift_binary_proto_read_set_end;
+  
+  VALUE method_table_object = Data_Wrap_Struct(rb_cObject, 0, free, npmt);
+  rb_const_set(bpa_class, rb_intern("@native_method_table"), method_table_object);
+}
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.h?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.h (added)
+++ incubator/thrift/trunk/lib/rb/ext/binary_protocol_accelerated.h Mon Feb  2 00:48:17 2009
@@ -0,0 +1,2 @@
+
+void Init_binary_protocol_accelerated();
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/constants.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/constants.h?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/constants.h (added)
+++ incubator/thrift/trunk/lib/rb/ext/constants.h Mon Feb  2 00:48:17 2009
@@ -0,0 +1,75 @@
+
+extern int TTYPE_STOP;
+extern int TTYPE_BOOL;
+extern int TTYPE_BYTE;
+extern int TTYPE_I16;
+extern int TTYPE_I32;
+extern int TTYPE_I64;
+extern int TTYPE_DOUBLE;
+extern int TTYPE_STRING;
+extern int TTYPE_MAP;
+extern int TTYPE_SET;
+extern int TTYPE_LIST;
+extern int TTYPE_STRUCT;
+
+extern ID validate_method_id;
+extern ID write_struct_begin_method_id;
+extern ID write_struct_end_method_id;
+extern ID write_field_begin_method_id;
+extern ID write_field_end_method_id;
+extern ID write_boolean_method_id;
+extern ID write_byte_method_id;
+extern ID write_i16_method_id;
+extern ID write_i32_method_id;
+extern ID write_i64_method_id;
+extern ID write_double_method_id;
+extern ID write_string_method_id;
+extern ID write_map_begin_method_id;
+extern ID write_map_end_method_id;
+extern ID write_list_begin_method_id;
+extern ID write_list_end_method_id;
+extern ID write_set_begin_method_id;
+extern ID write_set_end_method_id;
+extern ID size_method_id;
+extern ID read_bool_method_id;
+extern ID read_byte_method_id;
+extern ID read_i16_method_id;
+extern ID read_i32_method_id;
+extern ID read_i64_method_id;
+extern ID read_string_method_id;
+extern ID read_double_method_id;
+extern ID read_map_begin_method_id;
+extern ID read_map_end_method_id;
+extern ID read_list_begin_method_id;
+extern ID read_list_end_method_id;
+extern ID read_set_begin_method_id;
+extern ID read_set_end_method_id;
+extern ID read_struct_begin_method_id;
+extern ID read_struct_end_method_id;
+extern ID read_field_begin_method_id;
+extern ID read_field_end_method_id;
+extern ID keys_method_id;
+extern ID entries_method_id; 
+extern ID name_method_id; 
+extern ID sort_method_id;
+extern ID write_field_stop_method_id;
+extern ID skip_method_id;
+extern ID write_method_id;
+extern ID read_method_id;
+extern ID native_qmark_method_id;
+
+extern ID fields_const_id;
+extern ID transport_ivar_id;
+
+extern VALUE type_sym;
+extern VALUE name_sym;
+extern VALUE key_sym;
+extern VALUE value_sym;
+extern VALUE element_sym;
+extern VALUE class_sym;
+
+extern VALUE rb_cSet;
+extern VALUE thrift_module;
+extern VALUE thrift_types_module;
+extern VALUE class_thrift_protocol;
+extern VALUE protocol_exception_class;
\ No newline at end of file

Modified: incubator/thrift/trunk/lib/rb/ext/extconf.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/extconf.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/extconf.rb (original)
+++ incubator/thrift/trunk/lib/rb/ext/extconf.rb Mon Feb  2 00:48:17 2009
@@ -4,4 +4,4 @@
 
 have_func("strlcpy", "string.h")
 
-create_makefile 'binaryprotocolaccelerated'
+create_makefile 'thrift_native'

Added: incubator/thrift/trunk/lib/rb/ext/memory_buffer.c
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/memory_buffer.c?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/memory_buffer.c (added)
+++ incubator/thrift/trunk/lib/rb/ext/memory_buffer.c Mon Feb  2 00:48:17 2009
@@ -0,0 +1,52 @@
+#include <ruby.h>
+#include <constants.h>
+
+ID buf_ivar_id;
+ID index_ivar_id;
+
+ID slice_method_id;
+
+int GARBAGE_BUFFER_SIZE;
+
+#define GET_BUF(self) rb_ivar_get(self, buf_ivar_id)
+
+VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) {
+  VALUE buf = GET_BUF(self);
+  rb_str_buf_cat(buf, RSTRING(str)->ptr, RSTRING(str)->len);
+  return Qnil;
+}
+
+VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) {
+  int length = FIX2INT(length_value);
+  
+  VALUE index_value = rb_ivar_get(self, index_ivar_id);
+  int index = FIX2INT(index_value);
+  
+  VALUE buf = GET_BUF(self);
+  VALUE data = rb_funcall(buf, slice_method_id, 2, index_value, length_value);
+  
+  index += length;
+  if (index > RSTRING(buf)->len) {
+    index = RSTRING(buf)->len;
+  }
+  if (index >= GARBAGE_BUFFER_SIZE) {
+    rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(-1)));
+    index = 0;
+  }
+
+  rb_ivar_set(self, index_ivar_id, INT2FIX(index));
+  return data;
+}
+
+void Init_memory_buffer() {
+  VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBuffer"));
+  rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1);
+  rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1);
+  
+  buf_ivar_id = rb_intern("@buf");
+  index_ivar_id = rb_intern("@index");
+  
+  slice_method_id = rb_intern("slice");
+  
+  GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE")));
+}
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/memory_buffer.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/memory_buffer.h?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/memory_buffer.h (added)
+++ incubator/thrift/trunk/lib/rb/ext/memory_buffer.h Mon Feb  2 00:48:17 2009
@@ -0,0 +1,2 @@
+
+void Init_memory_buffer();
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/protocol.c
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/protocol.c?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/protocol.c (added)
+++ incubator/thrift/trunk/lib/rb/ext/protocol.c Mon Feb  2 00:48:17 2009
@@ -0,0 +1,166 @@
+#include <ruby.h>
+#include <protocol.h>
+#include <stdbool.h>
+#include <constants.h>
+#include <struct.h>
+
+static VALUE skip(VALUE self, int ttype) {
+  if (ttype == TTYPE_STOP) {
+    return Qnil;
+  } else if (ttype == TTYPE_BOOL) {
+    rb_funcall(self, read_bool_method_id, 0);
+  } else if (ttype == TTYPE_BYTE) {
+    rb_funcall(self, read_byte_method_id, 0);
+  } else if (ttype == TTYPE_I16) {
+    rb_funcall(self, read_i16_method_id, 0);
+  } else if (ttype == TTYPE_I32) {
+    rb_funcall(self, read_i32_method_id, 0);
+  } else if (ttype == TTYPE_I64) {
+    rb_funcall(self, read_i64_method_id, 0);
+  } else if (ttype == TTYPE_DOUBLE) {
+    rb_funcall(self, read_double_method_id, 0);
+  } else if (ttype == TTYPE_STRING) {
+    rb_funcall(self, read_string_method_id, 0);
+  } else if (ttype == TTYPE_STRUCT) {
+    rb_funcall(self, read_struct_begin_method_id, 0);
+    while (true) {
+      VALUE field_header = rb_funcall(self, read_field_begin_method_id, 0);
+      if (NIL_P(field_header) || FIX2INT(rb_ary_entry(field_header, 1)) == TTYPE_STOP ) {
+        break;
+      } 
+      skip(self, FIX2INT(rb_ary_entry(field_header, 1)));
+      rb_funcall(self, read_field_end_method_id, 0);
+    }
+    rb_funcall(self, read_struct_end_method_id, 0);
+  } else if (ttype == TTYPE_MAP) {
+    int i;
+    VALUE map_header = rb_funcall(self, read_map_begin_method_id, 0);
+    int ktype = FIX2INT(rb_ary_entry(map_header, 0));
+    int vtype = FIX2INT(rb_ary_entry(map_header, 1));
+    int size = FIX2INT(rb_ary_entry(map_header, 2));
+    
+    for (i = 0; i < size; i++) {
+      skip(self, ktype);
+      skip(self, vtype);
+    }
+    rb_funcall(self, read_map_end_method_id, 0);
+  } else if (ttype == TTYPE_LIST || ttype == TTYPE_SET) {
+    int i;
+    VALUE collection_header = rb_funcall(self, ttype == TTYPE_LIST ? read_list_begin_method_id : read_set_begin_method_id, 0);
+    int etype = FIX2INT(rb_ary_entry(collection_header, 0));
+    int size = FIX2INT(rb_ary_entry(collection_header, 1));
+    for (i = 0; i < size; i++) {
+      skip(self, etype);
+    }
+    rb_funcall(self, ttype == TTYPE_LIST ? read_list_end_method_id : read_set_end_method_id, 0);
+  } else {
+    rb_raise(rb_eNotImpError, "don't know how to skip type %d", ttype);
+  }
+
+  return Qnil;
+}
+
+VALUE rb_thrift_protocol_native_qmark(VALUE self) {
+  return Qfalse;
+}
+
+VALUE rb_thrift_protocol_skip(VALUE protocol, VALUE ttype) {
+  return skip(protocol, FIX2INT(ttype));
+}
+
+VALUE rb_thrift_write_message_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_struct_begin(VALUE self, VALUE name) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_struct_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_field_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_map_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_list_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_write_set_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thrift_read_message_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_struct_begin(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_struct_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_field_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_map_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_list_end(VALUE self) {
+  return Qnil;
+}
+
+VALUE rb_thift_read_set_end(VALUE self) {
+  return Qnil;
+}
+
+void Init_protocol() {
+  VALUE c_protocol = rb_const_get(thrift_module, rb_intern("Protocol"));
+  
+  rb_define_method(c_protocol, "skip", rb_thrift_protocol_skip, 1);
+  rb_define_method(c_protocol, "write_message_end", rb_thrift_write_message_end, 0);
+  rb_define_method(c_protocol, "write_struct_begin", rb_thrift_write_struct_begin, 1);
+  rb_define_method(c_protocol, "write_struct_end", rb_thrift_write_struct_end, 0);
+  rb_define_method(c_protocol, "write_field_end", rb_thrift_write_field_end, 0);
+  rb_define_method(c_protocol, "write_map_end", rb_thrift_write_map_end, 0);
+  rb_define_method(c_protocol, "write_list_end", rb_thrift_write_list_end, 0);
+  rb_define_method(c_protocol, "write_set_end", rb_thrift_write_set_end, 0);
+  rb_define_method(c_protocol, "read_message_end", rb_thrift_read_message_end, 0);
+  rb_define_method(c_protocol, "read_struct_begin", rb_thift_read_struct_begin, 0);
+  rb_define_method(c_protocol, "read_struct_end", rb_thift_read_struct_end, 0);
+  rb_define_method(c_protocol, "read_field_end", rb_thift_read_field_end, 0);
+  rb_define_method(c_protocol, "read_map_end", rb_thift_read_map_end, 0);
+  rb_define_method(c_protocol, "read_list_end", rb_thift_read_list_end, 0);
+  rb_define_method(c_protocol, "read_set_end", rb_thift_read_set_end, 0);
+  rb_define_method(c_protocol, "native?", rb_thrift_protocol_native_qmark, 0);
+  
+  // native_proto_method_table *npmt;
+  // npmt = ALLOC(native_proto_method_table);
+  // npmt->write_message_end = rb_thrift_write_message_end;
+  // npmt->write_struct_begin = rb_thrift_write_struct_begin;
+  // npmt->write_struct_end = rb_thrift_write_struct_end;
+  // npmt->write_field_end = rb_thrift_write_field_end;
+  // npmt->write_map_end = rb_thrift_write_map_end;
+  // npmt->write_list_end = rb_thrift_write_list_end;
+  // npmt->write_set_end = rb_thrift_write_set_end;
+  // npmt->read_message_end = rb_thrift_read_message_end;
+  // npmt->read_struct_begin = rb_thift_read_struct_begin;
+  // npmt->read_struct_end = rb_thift_read_struct_end;
+  // npmt->read_field_end = rb_thift_read_field_end;
+  // npmt->read_map_end = rb_thift_read_map_end;
+  // npmt->read_list_end = rb_thift_read_list_end;
+  // npmt->read_set_end = rb_thift_read_set_end;
+  // 
+  // VALUE method_table_object = Data_Wrap_Struct(rb_cObject, 0, free, npmt);
+  // rb_const_set(c_protocol, rb_intern("@native_method_table"), method_table_object);
+}
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/protocol.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/protocol.h?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/protocol.h (added)
+++ incubator/thrift/trunk/lib/rb/ext/protocol.h Mon Feb  2 00:48:17 2009
@@ -0,0 +1,2 @@
+
+void Init_protocol();
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/struct.c
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/struct.c?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/struct.c (added)
+++ incubator/thrift/trunk/lib/rb/ext/struct.c Mon Feb  2 00:48:17 2009
@@ -0,0 +1,553 @@
+
+#include <struct.h>
+#include <constants.h>
+
+static native_proto_method_table *mt;
+
+#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
+#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
+
+//-------------------------------------------
+// Writing section
+//-------------------------------------------
+
+// default fn pointers for protocol stuff here
+
+VALUE default_write_bool(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_boolean_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_byte(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_byte_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_i16(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_i16_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_i32(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_i32_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_i64(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_i64_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_double(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_double_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_string(VALUE protocol, VALUE value) {
+  rb_funcall(protocol, write_string_method_id, 1, value);
+  return Qnil;
+}
+
+VALUE default_write_list_begin(VALUE protocol, VALUE etype, VALUE length) {
+  rb_funcall(protocol, write_list_begin_method_id, 2, etype, length);
+  return Qnil;
+}
+
+VALUE default_write_list_end(VALUE protocol) {
+  rb_funcall(protocol, write_list_end_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_write_set_begin(VALUE protocol, VALUE etype, VALUE length) {
+  rb_funcall(protocol, write_set_begin_method_id, 2, etype, length);
+  return Qnil;
+}
+
+VALUE default_write_set_end(VALUE protocol) {
+  rb_funcall(protocol, write_set_end_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_write_map_begin(VALUE protocol, VALUE ktype, VALUE vtype, VALUE length) {
+  rb_funcall(protocol, write_map_begin_method_id, 3, ktype, vtype, length);
+  return Qnil;
+}
+
+VALUE default_write_map_end(VALUE protocol) {
+  rb_funcall(protocol, write_map_end_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_write_struct_begin(VALUE protocol, VALUE struct_name) {
+  rb_funcall(protocol, write_struct_begin_method_id, 1, struct_name);
+  return Qnil;
+}
+
+VALUE default_write_struct_end(VALUE protocol) {
+  rb_funcall(protocol, write_struct_end_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_write_field_begin(VALUE protocol, VALUE name, VALUE type, VALUE id) {
+  rb_funcall(protocol, write_field_begin_method_id, 3, name, type, id);
+  return Qnil;
+}
+
+VALUE default_write_field_end(VALUE protocol) {
+  rb_funcall(protocol, write_field_end_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_write_field_stop(VALUE protocol) {
+  rb_funcall(protocol, write_field_stop_method_id, 0);
+  return Qnil;
+}
+
+VALUE default_read_field_begin(VALUE protocol) {
+  return rb_funcall(protocol, read_field_begin_method_id, 0);
+}
+
+VALUE default_read_field_end(VALUE protocol) {
+  return rb_funcall(protocol, read_field_end_method_id, 0);
+}
+
+VALUE default_read_map_begin(VALUE protocol) {
+  return rb_funcall(protocol, read_map_begin_method_id, 0);
+}
+
+VALUE default_read_map_end(VALUE protocol) {
+  return rb_funcall(protocol, read_map_end_method_id, 0);
+}
+
+VALUE default_read_list_begin(VALUE protocol) {
+  return rb_funcall(protocol, read_list_begin_method_id, 0);
+}
+
+VALUE default_read_list_end(VALUE protocol) {
+  return rb_funcall(protocol, read_list_end_method_id, 0);
+}
+
+VALUE default_read_set_begin(VALUE protocol) {
+  return rb_funcall(protocol, read_set_begin_method_id, 0);
+}
+
+VALUE default_read_set_end(VALUE protocol) {
+  return rb_funcall(protocol, read_set_end_method_id, 0);
+}
+
+VALUE default_read_byte(VALUE protocol) {
+  return rb_funcall(protocol, read_byte_method_id, 0);
+}
+
+VALUE default_read_bool(VALUE protocol) {
+  return rb_funcall(protocol, read_bool_method_id, 0);
+}
+
+VALUE default_read_i16(VALUE protocol) {
+  return rb_funcall(protocol, read_i16_method_id, 0);
+}
+
+VALUE default_read_i32(VALUE protocol) {
+  return rb_funcall(protocol, read_i32_method_id, 0);
+}
+
+VALUE default_read_i64(VALUE protocol) {
+  return rb_funcall(protocol, read_i64_method_id, 0);
+}
+
+VALUE default_read_double(VALUE protocol) {
+  return rb_funcall(protocol, read_double_method_id, 0);
+}
+
+VALUE default_read_string(VALUE protocol) {
+  return rb_funcall(protocol, read_string_method_id, 0);
+}
+
+VALUE default_read_struct_begin(VALUE protocol) {
+  return rb_funcall(protocol, read_struct_begin_method_id, 0);
+}
+
+VALUE default_read_struct_end(VALUE protocol) {
+  return rb_funcall(protocol, read_struct_end_method_id, 0);
+}
+
+static void set_default_proto_function_pointers() {
+  mt = ALLOC(native_proto_method_table);
+  
+  mt->write_field_begin = default_write_field_begin;
+  mt->write_field_stop = default_write_field_stop;
+  mt->write_map_begin = default_write_map_begin;
+  mt->write_map_end = default_write_map_end;
+  mt->write_list_begin = default_write_list_begin;
+  mt->write_list_end = default_write_list_end;
+  mt->write_set_begin = default_write_set_begin;
+  mt->write_set_end = default_write_set_end;
+  mt->write_byte = default_write_byte;
+  mt->write_bool = default_write_bool;
+  mt->write_i16 = default_write_i16;
+  mt->write_i32 = default_write_i32;
+  mt->write_i64 = default_write_i64;
+  mt->write_double = default_write_double;
+  mt->write_string = default_write_string;
+  mt->write_struct_begin = default_write_struct_begin;
+  mt->write_struct_end = default_write_struct_end;
+  mt->write_field_end = default_write_field_end;
+
+  mt->read_struct_begin = default_read_struct_begin;
+  mt->read_struct_end = default_read_struct_end;
+  mt->read_field_begin = default_read_field_begin;
+  mt->read_field_end = default_read_field_end;
+  mt->read_map_begin = default_read_map_begin;
+  mt->read_map_end = default_read_map_end;
+  mt->read_list_begin = default_read_list_begin;
+  mt->read_list_end = default_read_list_end;
+  mt->read_set_begin = default_read_set_begin;
+  mt->read_set_end = default_read_set_end;
+  mt->read_byte = default_read_byte;
+  mt->read_bool = default_read_bool;
+  mt->read_i16 = default_read_i16;
+  mt->read_i32 = default_read_i32;
+  mt->read_i64 = default_read_i64;
+  mt->read_double = default_read_double;
+  mt->read_string = default_read_string;
+  
+}
+
+static void set_native_proto_function_pointers(VALUE protocol) {
+  VALUE method_table_object = rb_const_get(CLASS_OF(protocol), rb_intern("@native_method_table"));
+  // TODO: check nil?
+  Data_Get_Struct(method_table_object, native_proto_method_table, mt);
+}
+
+// end default protocol methods
+
+
+static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol);
+static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info);
+
+VALUE get_field_value(VALUE obj, VALUE field_name) {
+  char name_buf[RSTRING(field_name)->len + 1];
+  
+  name_buf[0] = '@';
+  strlcpy(&name_buf[1], RSTRING(field_name)->ptr, sizeof(name_buf));
+
+  VALUE value = rb_ivar_get(obj, rb_intern(name_buf));
+  
+  return value;
+}
+
+static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) {
+  int sz, i;
+  
+  if (ttype == TTYPE_MAP) {
+    VALUE keys;
+    VALUE key;
+    VALUE val;
+
+    Check_Type(value, T_HASH);
+    
+    VALUE key_info = rb_hash_aref(field_info, key_sym);
+    VALUE keytype_value = rb_hash_aref(key_info, type_sym);
+    int keytype = FIX2INT(keytype_value);
+    
+    VALUE value_info = rb_hash_aref(field_info, value_sym);
+    VALUE valuetype_value = rb_hash_aref(value_info, type_sym);
+    int valuetype = FIX2INT(valuetype_value);
+    
+    keys = rb_funcall(value, keys_method_id, 0);
+    
+    sz = RARRAY(keys)->len;
+    
+    mt->write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));
+    
+    for (i = 0; i < sz; i++) {
+      key = rb_ary_entry(keys, i);
+      val = rb_hash_aref(value, key);
+      
+      if (IS_CONTAINER(keytype)) {
+        write_container(keytype, key_info, key, protocol);
+      } else {
+        write_anything(keytype, key, protocol, key_info);
+      }
+      
+      if (IS_CONTAINER(valuetype)) {
+        write_container(valuetype, value_info, val, protocol);
+      } else {
+        write_anything(valuetype, val, protocol, value_info);
+      }
+    }
+    
+    mt->write_map_end(protocol);
+  } else if (ttype == TTYPE_LIST) {
+    Check_Type(value, T_ARRAY);
+
+    sz = RARRAY(value)->len;
+
+    VALUE element_type_info = rb_hash_aref(field_info, element_sym);
+    VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
+    int element_type = FIX2INT(element_type_value);
+    
+    mt->write_list_begin(protocol, element_type_value, INT2FIX(sz));
+    for (i = 0; i < sz; ++i) {
+      VALUE val = rb_ary_entry(value, i);
+      if (IS_CONTAINER(element_type)) {
+        write_container(element_type, element_type_info, val, protocol);
+      } else {
+        write_anything(element_type, val, protocol, element_type_info);
+      }
+    }
+    mt->write_list_end(protocol);
+  } else if (ttype == TTYPE_SET) {
+    VALUE items;
+
+    if (TYPE(value) == T_ARRAY) {
+      items = value;
+    } else {        
+      if (rb_cSet == CLASS_OF(value)) {
+        items = rb_funcall(value, entries_method_id, 0);
+      } else {
+        Check_Type(value, T_HASH);
+        items = rb_funcall(value, keys_method_id, 0);
+      }
+    }
+
+    sz = RARRAY(items)->len;
+
+    VALUE element_type_info = rb_hash_aref(field_info, element_sym);
+    VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
+    int element_type = FIX2INT(element_type_value);
+    
+    mt->write_set_begin(protocol, element_type_value, INT2FIX(sz));
+    
+    for (i = 0; i < sz; i++) {
+      VALUE val = rb_ary_entry(items, i);
+      if (IS_CONTAINER(element_type)) {
+        write_container(element_type, element_type_info, val, protocol);
+      } else {
+        write_anything(element_type, val, protocol, element_type_info);
+      }
+    }
+    
+    mt->write_set_end(protocol);
+  } else {
+    rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype);
+  }
+}
+
+static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info) {
+  if (ttype == TTYPE_BOOL) {
+    mt->write_bool(protocol, value);
+  } else if (ttype == TTYPE_BYTE) {
+    mt->write_byte(protocol, value);
+  } else if (ttype == TTYPE_I16) {
+    mt->write_i16(protocol, value);
+  } else if (ttype == TTYPE_I32) {
+    mt->write_i32(protocol, value);
+  } else if (ttype == TTYPE_I64) {
+    mt->write_i64(protocol, value);
+  } else if (ttype == TTYPE_DOUBLE) {
+    mt->write_double(protocol, value);
+  } else if (ttype == TTYPE_STRING) {
+    mt->write_string(protocol, value);
+  } else if (IS_CONTAINER(ttype)) {
+    write_container(ttype, field_info, value, protocol);
+  } else if (ttype == TTYPE_STRUCT) {
+    rb_thrift_struct_write(value, protocol);
+  } else {
+    rb_raise(rb_eNotImpError, "Unknown type for binary_encoding: %d", ttype);
+  }
+}
+
+static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) {
+  // call validate
+  rb_funcall(self, validate_method_id, 0);
+
+  if (RTEST(rb_funcall(protocol, native_qmark_method_id, 0))) {
+    set_native_proto_function_pointers(protocol);
+  } else {
+    set_default_proto_function_pointers();
+  }
+  
+  // write struct begin
+  mt->write_struct_begin(protocol, rb_class_name(CLASS_OF(self)));
+  
+  // iterate through all the fields here
+  VALUE struct_fields = STRUCT_FIELDS(self);
+  VALUE struct_field_ids_unordered = rb_funcall(struct_fields, keys_method_id, 0);
+  VALUE struct_field_ids_ordered = rb_funcall(struct_field_ids_unordered, sort_method_id, 0);
+  
+  int i = 0;
+  for (i=0; i < RARRAY(struct_field_ids_ordered)->len; i++) {
+    VALUE field_id = rb_ary_entry(struct_field_ids_ordered, i);
+    VALUE field_info = rb_hash_aref(struct_fields, field_id);
+
+    VALUE ttype_value = rb_hash_aref(field_info, type_sym);
+    int ttype = FIX2INT(ttype_value);
+    VALUE field_name = rb_hash_aref(field_info, name_sym);
+    VALUE field_value = get_field_value(self, field_name);
+
+    if (!NIL_P(field_value)) {
+      mt->write_field_begin(protocol, field_name, ttype_value, field_id);
+      
+      write_anything(ttype, field_value, protocol, field_info);
+      
+      mt->write_field_end(protocol);
+    }
+  }
+  
+  mt->write_field_stop(protocol);
+  
+  // write struct end
+  mt->write_struct_end(protocol);
+  
+  return Qnil;
+}
+
+//-------------------------------------------
+// Reading section
+//-------------------------------------------
+
+static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol);
+
+static void set_field_value(VALUE obj, VALUE field_name, VALUE value) {
+  char name_buf[RSTRING(field_name)->len + 1];
+
+  name_buf[0] = '@';
+  strlcpy(&name_buf[1], RSTRING(field_name)->ptr, sizeof(name_buf));
+
+  rb_ivar_set(obj, rb_intern(name_buf), value);
+}
+
+static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
+  VALUE result = Qnil;
+  
+  if (ttype == TTYPE_BOOL) {
+    result = mt->read_bool(protocol);
+  } else if (ttype == TTYPE_BYTE) {
+    result = mt->read_byte(protocol);
+  } else if (ttype == TTYPE_I16) {
+    result = mt->read_i16(protocol);
+  } else if (ttype == TTYPE_I32) {
+    result = mt->read_i32(protocol);
+  } else if (ttype == TTYPE_I64) {
+    result = mt->read_i64(protocol);
+  } else if (ttype == TTYPE_STRING) {
+    result = mt->read_string(protocol);
+  } else if (ttype == TTYPE_DOUBLE) {
+    result = mt->read_double(protocol);
+  } else if (ttype == TTYPE_STRUCT) {
+    VALUE klass = rb_hash_aref(field_info, class_sym);
+    result = rb_class_new_instance(0, NULL, klass);
+    rb_thrift_struct_read(result, protocol);
+  } else if (ttype == TTYPE_MAP) {
+    int i;
+
+    VALUE map_header = mt->read_map_begin(protocol);
+    int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
+    int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
+    int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
+    
+    VALUE key_info = rb_hash_aref(field_info, key_sym);
+    VALUE value_info = rb_hash_aref(field_info, value_sym);
+
+    result = rb_hash_new();
+    
+    for (i = 0; i < num_entries; ++i) {
+      VALUE key, val;
+      
+      key = read_anything(protocol, key_ttype, key_info);
+      val = read_anything(protocol, value_ttype, value_info);
+      
+      rb_hash_aset(result, key, val);
+    }
+    
+    mt->read_map_end(protocol);
+  } else if (ttype == TTYPE_LIST) {
+    int i;
+
+    VALUE list_header = mt->read_list_begin(protocol);
+    int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
+    int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
+    result = rb_ary_new2(num_elements);
+    
+    for (i = 0; i < num_elements; ++i) {
+      rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
+    }
+
+
+    mt->read_list_end(protocol);
+  } else if (ttype == TTYPE_SET) {
+    VALUE items;
+    int i;
+
+    VALUE set_header = mt->read_set_begin(protocol);
+    int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
+    int num_elements = FIX2INT(rb_ary_entry(set_header, 1));
+    items = rb_ary_new2(num_elements);
+    
+    for (i = 0; i < num_elements; ++i) {
+      rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
+    }
+    
+
+    mt->read_set_end(protocol);
+    
+    result = rb_class_new_instance(1, &items, rb_cSet);
+  } else {
+    rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype);
+  }
+  
+  return result;
+}
+
+static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol) {
+  // read struct begin
+  mt->read_struct_begin(protocol);
+
+  VALUE struct_fields = STRUCT_FIELDS(self);
+  
+  // read each field
+  while (true) {
+    VALUE field_header = rb_funcall(protocol, read_field_begin_method_id, 0);
+    VALUE field_type_value = rb_ary_entry(field_header, 1);
+    int field_type = FIX2INT(field_type_value);
+    
+    if (field_type == TTYPE_STOP) {
+      break;
+    }
+
+    // make sure we got a type we expected
+    VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2));
+
+    if (!NIL_P(field_info)) {
+      int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym));
+      if (field_type == specified_type) {
+        // read the value
+        VALUE name = rb_hash_aref(field_info, name_sym);
+        set_field_value(self, name, read_anything(protocol, field_type, field_info));
+      } else {
+        rb_funcall(protocol, skip_method_id, 1, field_type_value);
+      }
+    } else {
+      rb_funcall(protocol, skip_method_id, 1, field_type_value);
+    }
+    
+    // read field end
+    mt->read_field_end(protocol);
+  }
+  
+  // read struct end
+  mt->read_struct_end(protocol);
+  
+  return Qnil;
+}
+
+void Init_struct() {
+  VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct"));
+  
+  rb_define_method(struct_module, "write", rb_thrift_struct_write, 1);
+  rb_define_method(struct_module, "read", rb_thrift_struct_read, 1);
+  
+  set_default_proto_function_pointers();
+}
+

Added: incubator/thrift/trunk/lib/rb/ext/struct.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/struct.h?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/struct.h (added)
+++ incubator/thrift/trunk/lib/rb/ext/struct.h Mon Feb  2 00:48:17 2009
@@ -0,0 +1,48 @@
+#include <stdbool.h>
+#include <ruby.h>
+
+typedef struct native_proto_method_table {
+  VALUE (*write_bool)(VALUE, VALUE);
+  VALUE (*write_byte)(VALUE, VALUE);
+  VALUE (*write_i16)(VALUE, VALUE);
+  VALUE (*write_i32)(VALUE, VALUE);
+  VALUE (*write_i64)(VALUE, VALUE);
+  VALUE (*write_double)(VALUE, VALUE);
+  VALUE (*write_string)(VALUE, VALUE);
+  VALUE (*write_list_begin)(VALUE, VALUE, VALUE);
+  VALUE (*write_list_end)(VALUE);
+  VALUE (*write_set_begin)(VALUE, VALUE, VALUE);
+  VALUE (*write_set_end)(VALUE);
+  VALUE (*write_map_begin)(VALUE, VALUE, VALUE, VALUE);
+  VALUE (*write_map_end)(VALUE);
+  VALUE (*write_struct_begin)(VALUE, VALUE);
+  VALUE (*write_struct_end)(VALUE);
+  VALUE (*write_field_begin)(VALUE, VALUE, VALUE, VALUE);
+  VALUE (*write_field_end)(VALUE);
+  VALUE (*write_field_stop)(VALUE);
+  VALUE (*write_message_begin)(VALUE, VALUE, VALUE, VALUE);
+  VALUE (*write_message_end)(VALUE);
+  
+  VALUE (*read_message_begin)(VALUE);
+  VALUE (*read_message_end)(VALUE);
+  VALUE (*read_field_begin)(VALUE);
+  VALUE (*read_field_end)(VALUE);
+  VALUE (*read_map_begin)(VALUE);
+  VALUE (*read_map_end)(VALUE);
+  VALUE (*read_list_begin)(VALUE);
+  VALUE (*read_list_end)(VALUE);
+  VALUE (*read_set_begin)(VALUE);
+  VALUE (*read_set_end)(VALUE);
+  VALUE (*read_byte)(VALUE);
+  VALUE (*read_bool)(VALUE);
+  VALUE (*read_i16)(VALUE);
+  VALUE (*read_i32)(VALUE);
+  VALUE (*read_i64)(VALUE);
+  VALUE (*read_double)(VALUE);
+  VALUE (*read_string)(VALUE);
+  VALUE (*read_struct_begin)(VALUE);
+  VALUE (*read_struct_end)(VALUE);
+  
+} native_proto_method_table;
+
+void Init_struct();
\ No newline at end of file

Added: incubator/thrift/trunk/lib/rb/ext/thrift_native.c
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/ext/thrift_native.c?rev=739895&view=auto
==============================================================================
--- incubator/thrift/trunk/lib/rb/ext/thrift_native.c (added)
+++ incubator/thrift/trunk/lib/rb/ext/thrift_native.c Mon Feb  2 00:48:17 2009
@@ -0,0 +1,169 @@
+#include <ruby.h>
+#include <struct.h>
+#include <binary_protocol_accelerated.h>
+#include <protocol.h>
+#include <memory_buffer.h>
+
+// cached classes/modules
+VALUE rb_cSet;
+VALUE thrift_module;
+VALUE thrift_types_module;
+
+// TType constants
+int TTYPE_STOP;
+int TTYPE_BOOL;
+int TTYPE_BYTE;
+int TTYPE_I16;
+int TTYPE_I32;
+int TTYPE_I64;
+int TTYPE_DOUBLE;
+int TTYPE_STRING;
+int TTYPE_MAP;
+int TTYPE_SET;
+int TTYPE_LIST;
+int TTYPE_STRUCT;
+
+// method ids
+ID validate_method_id;
+ID write_struct_begin_method_id;
+ID write_struct_end_method_id;
+ID write_field_begin_method_id;
+ID write_field_end_method_id;
+ID write_boolean_method_id;
+ID write_byte_method_id;
+ID write_i16_method_id;
+ID write_i32_method_id;
+ID write_i64_method_id;
+ID write_double_method_id;
+ID write_string_method_id;
+ID write_map_begin_method_id;
+ID write_map_end_method_id;
+ID write_list_begin_method_id;
+ID write_list_end_method_id;
+ID write_set_begin_method_id;
+ID write_set_end_method_id;
+ID size_method_id;
+ID read_bool_method_id;
+ID read_byte_method_id;
+ID read_i16_method_id;
+ID read_i32_method_id;
+ID read_i64_method_id;
+ID read_string_method_id;
+ID read_double_method_id;
+ID read_map_begin_method_id;
+ID read_map_end_method_id;
+ID read_list_begin_method_id;
+ID read_list_end_method_id;
+ID read_set_begin_method_id;
+ID read_set_end_method_id;
+ID read_struct_begin_method_id;
+ID read_struct_end_method_id;
+ID read_field_begin_method_id;
+ID read_field_end_method_id;
+ID keys_method_id;
+ID entries_method_id; 
+ID name_method_id; 
+ID sort_method_id;
+ID write_field_stop_method_id;
+ID skip_method_id;
+ID write_method_id;
+ID read_method_id;
+ID native_qmark_method_id;
+
+// constant ids
+ID fields_const_id;
+ID transport_ivar_id;
+
+// cached symbols
+VALUE type_sym;
+VALUE name_sym;
+VALUE key_sym;
+VALUE value_sym;
+VALUE element_sym;
+VALUE class_sym;
+VALUE protocol_exception_class;
+
+void Init_thrift_native() {
+  // cached classes
+  thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
+  thrift_types_module = rb_const_get(thrift_module, rb_intern("Types"));
+  rb_cSet = rb_const_get(rb_cObject, rb_intern("Set"));
+  protocol_exception_class = rb_const_get(thrift_module, rb_intern("ProtocolException"));
+  
+  // Init ttype constants
+  TTYPE_BOOL = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BOOL")));
+  TTYPE_BYTE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BYTE")));
+  TTYPE_I16 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I16")));
+  TTYPE_I32 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I32")));
+  TTYPE_I64 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I64")));
+  TTYPE_DOUBLE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("DOUBLE")));
+  TTYPE_STRING = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRING")));
+  TTYPE_MAP = FIX2INT(rb_const_get(thrift_types_module, rb_intern("MAP")));
+  TTYPE_SET = FIX2INT(rb_const_get(thrift_types_module, rb_intern("SET")));
+  TTYPE_LIST = FIX2INT(rb_const_get(thrift_types_module, rb_intern("LIST")));
+  TTYPE_STRUCT = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRUCT")));
+
+  // method ids
+  validate_method_id = rb_intern("validate");
+  write_struct_begin_method_id = rb_intern("write_struct_begin");
+  write_struct_end_method_id = rb_intern("write_struct_end");
+  write_field_begin_method_id = rb_intern("write_field_begin");
+  write_field_end_method_id = rb_intern("write_field_end");
+  write_boolean_method_id = rb_intern("write_bool");
+  write_byte_method_id = rb_intern("write_byte");
+  write_i16_method_id = rb_intern("write_i16");
+  write_i32_method_id = rb_intern("write_i32");
+  write_i64_method_id = rb_intern("write_i64");
+  write_double_method_id = rb_intern("write_double");
+  write_string_method_id = rb_intern("write_string");
+  write_map_begin_method_id = rb_intern("write_map_begin");
+  write_map_end_method_id = rb_intern("write_map_end");
+  write_list_begin_method_id = rb_intern("write_list_begin");
+  write_list_end_method_id = rb_intern("write_list_end");
+  write_set_begin_method_id = rb_intern("write_set_begin");
+  write_set_end_method_id = rb_intern("write_set_end");
+  size_method_id = rb_intern("size");
+  read_bool_method_id = rb_intern("read_bool");
+  read_byte_method_id = rb_intern("read_byte");
+  read_i16_method_id = rb_intern("read_i16");
+  read_i32_method_id = rb_intern("read_i32");
+  read_i64_method_id = rb_intern("read_i64");
+  read_string_method_id = rb_intern("read_string");
+  read_double_method_id = rb_intern("read_double");
+  read_map_begin_method_id = rb_intern("read_map_begin");
+  read_map_end_method_id = rb_intern("read_map_end");  
+  read_list_begin_method_id = rb_intern("read_list_begin");
+  read_list_end_method_id = rb_intern("read_list_end");
+  read_set_begin_method_id = rb_intern("read_set_begin");
+  read_set_end_method_id = rb_intern("read_set_end");
+  read_struct_begin_method_id = rb_intern("read_struct_begin");
+  read_struct_end_method_id = rb_intern("read_struct_end");
+  read_field_begin_method_id = rb_intern("read_field_begin");
+  read_field_end_method_id = rb_intern("read_field_end");
+  keys_method_id = rb_intern("keys");
+  entries_method_id = rb_intern("entries");
+  name_method_id = rb_intern("name");
+  sort_method_id = rb_intern("sort");
+  write_field_stop_method_id = rb_intern("write_field_stop");
+  skip_method_id = rb_intern("skip");
+  write_method_id = rb_intern("write");
+  read_method_id = rb_intern("read");
+  native_qmark_method_id = rb_intern("native?");
+  
+  // constant ids
+  fields_const_id = rb_intern("FIELDS");
+  transport_ivar_id = rb_intern("@trans");
+  
+  // cached symbols
+  type_sym = ID2SYM(rb_intern("type"));
+  name_sym = ID2SYM(rb_intern("name"));
+  key_sym = ID2SYM(rb_intern("key"));
+  value_sym = ID2SYM(rb_intern("value"));
+  element_sym = ID2SYM(rb_intern("element"));
+  class_sym = ID2SYM(rb_intern("class"));
+
+  Init_protocol();
+  Init_struct();
+  Init_binary_protocol_accelerated();
+  Init_memory_buffer();
+}
\ No newline at end of file

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/protocol.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/protocol.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/protocol.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/protocol.rb Mon Feb  2 00:48:17 2009
@@ -38,6 +38,11 @@
       @trans = trans
     end
 
+    def native?
+      puts "wrong method is being called!"
+      false
+    end
+
     def write_message_begin(name, type, seqid); nil; end
     deprecate! :writeMessageBegin => :write_message_begin
 

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocol.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocol.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocol.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocol.rb Mon Feb  2 00:48:17 2009
@@ -15,7 +15,10 @@
     VERSION_1 = 0x80010000
 
     def write_message_begin(name, type, seqid)
-      write_i32(VERSION_1 | type)
+      # this is necessary because we added (needed) bounds checking to 
+      # write_i32, and 0x80010000 is too big for that.
+      write_i16(VERSION_1 >> 16)
+      write_i16(type)
       write_string(name)
       write_i32(seqid)
     end
@@ -58,6 +61,7 @@
     end
 
     def write_i32(i32)
+      raise RangeError if i32 < -2**31 || i32 >= 2**31
       trans.write([i32].pack('N'))
     end
 

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocolaccelerated.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocolaccelerated.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocolaccelerated.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/protocol/binaryprotocolaccelerated.rb Mon Feb  2 00:48:17 2009
@@ -1,5 +1,5 @@
 require 'thrift/protocol/binaryprotocol'
-require 'binaryprotocolaccelerated'
+require 'thrift_native'
 
 =begin
 The only change required for a transport to support TBinaryProtocolAccelerated is to implement 2 methods:

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=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/struct.rb Mon Feb  2 00:48:17 2009
@@ -102,10 +102,10 @@
 
     def write(oprot)
       validate
-      if oprot.respond_to?(:encode_binary)
-        # TODO(kevinclark): Clean this so I don't have to access the transport.
-        oprot.trans.write oprot.encode_binary(self)
-      else
+      # if oprot.respond_to?(:encode_binary)
+      #   # TODO(kevinclark): Clean this so I don't have to access the transport.
+      #   oprot.trans.write oprot.encode_binary(self)
+      # else
         oprot.write_struct_begin(self.class.name)
         each_field do |fid, type, name|
           unless (value = instance_variable_get("@#{name}")).nil?
@@ -120,7 +120,7 @@
         end
         oprot.write_field_stop
         oprot.write_struct_end
-      end
+      # end
     end
 
     def ==(other)

Modified: incubator/thrift/trunk/lib/rb/lib/thrift/thrift.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/lib/thrift/thrift.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/lib/thrift/thrift.rb (original)
+++ incubator/thrift/trunk/lib/rb/lib/thrift/thrift.rb Mon Feb  2 00:48:17 2009
@@ -7,3 +7,8 @@
 require 'thrift/exceptions'
 require 'thrift/client'
 require 'thrift/struct'
+begin
+  require "thrift_native"
+rescue
+  puts "Could not load thrift_native libraries. Using pure ruby version."
+end
\ No newline at end of file

Modified: incubator/thrift/trunk/lib/rb/spec/binaryprotocol_spec_shared.rb
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/rb/spec/binaryprotocol_spec_shared.rb?rev=739895&r1=739894&r2=739895&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/rb/spec/binaryprotocol_spec_shared.rb (original)
+++ incubator/thrift/trunk/lib/rb/spec/binaryprotocol_spec_shared.rb Mon Feb  2 00:48:17 2009
@@ -2,7 +2,7 @@
 
 shared_examples_for 'a binary protocol' do
   before(:each) do
-    @trans = mock("MockTransport")
+    @trans = Thrift::MemoryBuffer.new
     @prot = protocol_class.new(@trans)
   end
 
@@ -12,295 +12,241 @@
   end
 
   it "should write the message header" do
-    @prot.should_receive(:write_i32).with(protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL).ordered
-    @prot.should_receive(:write_string).with('testMessage').ordered
-    @prot.should_receive(:write_i32).with(17).ordered
     @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
+    @trans.read(1000).should == [protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N")
   end
 
   # message footer is a noop
 
   it "should write the field header" do
-    @prot.should_receive(:write_byte).with(Thrift::Types::DOUBLE).ordered
-    @prot.should_receive(:write_i16).with(3).ordered
     @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3)
+    @trans.read(1000).should == [Thrift::Types::DOUBLE, 3].pack("cn")
   end
-
+  
   # field footer is a noop
-
+  
   it "should write the STOP field" do
-    @prot.should_receive(:write_byte).with(Thrift::Types::STOP)
     @prot.write_field_stop
+    @trans.read(1).should == "\000"
   end
-
+  
   it "should write the map header" do
-    @prot.should_receive(:write_byte).with(Thrift::Types::STRING).ordered
-    @prot.should_receive(:write_byte).with(Thrift::Types::LIST).ordered
-    @prot.should_receive(:write_i32).with(17).ordered
     @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17)
+    @trans.read(1000).should == [Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN");
   end
-
+   
   # map footer is a noop
-
+  
   it "should write the list header" do
-    @prot.should_receive(:write_byte).with(Thrift::Types::I16).ordered
-    @prot.should_receive(:write_i32).with(42).ordered
     @prot.write_list_begin(Thrift::Types::I16, 42)
+    @trans.read(1000).should == [Thrift::Types::I16, 42].pack("cN")
   end
-
+  
   # list footer is a noop
-
+  
   it "should write the set header" do
-    @prot.should_receive(:write_byte).with(Thrift::Types::BOOL).ordered
-    @prot.should_receive(:write_i32).with(2).ordered
-    @prot.write_set_begin(Thrift::Types::BOOL, 2)
+    @prot.write_set_begin(Thrift::Types::I16, 42)
+    @trans.read(1000).should == [Thrift::Types::I16, 42].pack("cN")
   end
-
+  
   it "should write a bool" do
-    @prot.should_receive(:write_byte).with(1).ordered
     @prot.write_bool(true)
-    @prot.should_receive(:write_byte).with(0).ordered
     @prot.write_bool(false)
+    @trans.read(1000).should == "\001\000"
   end
-
+  
   it "should treat a nil bool as false" do
-    @prot.should_receive(:write_byte).with(0)
     @prot.write_bool(nil)
+    @trans.read(1).should == "\000"
   end
-
+  
   it "should write a byte" do
     # byte is small enough, let's check -128..127
     (-128..127).each do |i|
-      @trans.should_receive(:write).with([i].pack('c')).ordered
       @prot.write_byte(i)
+      @trans.read(1).should == [i].pack('c')
     end
     (-128..127).each do |i|
     end
     # handing it numbers out of signed range should clip
     @trans.rspec_verify
     (128..255).each do |i|
-      @trans.should_receive(:write).with([i].pack('c')).ordered
       @prot.write_byte(i)
+      @trans.read(1).should == [i].pack('c')
     end
     # and lastly, a Bignum is going to error out
     lambda { @prot.write_byte(2**65) }.should raise_error(RangeError)
   end
-
+  
   it "should error gracefully when trying to write a nil byte" do
     lambda { @prot.write_byte(nil) }.should raise_error
   end
-
+  
   it "should write an i16" do
     # try a random scattering of values
     # include the signed i16 minimum/maximum
-    @trans.should_receive(:write).with("\200\000").ordered
-    @trans.should_receive(:write).with("\374\000").ordered
-    @trans.should_receive(:write).with("\000\021").ordered
-    @trans.should_receive(:write).with("\000\000").ordered
-    @trans.should_receive(:write).with("\330\360").ordered
-    @trans.should_receive(:write).with("\006\273").ordered
-    @trans.should_receive(:write).with("\177\377").ordered
     [-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i|
       @prot.write_i16(i)
     end
     # and try something out of signed range, it should clip
-    @trans.should_receive(:write).with("\200\005").ordered
     @prot.write_i16(2**15 + 5)
+    
+    @trans.read(1000).should == "\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005"
+    
     # a Bignum should error
     # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError)
   end
-
+  
   it "should error gracefully when trying to write a nil i16" do
     lambda { @prot.write_i16(nil) }.should raise_error
   end
-
+  
   it "should write an i32" do
     # try a random scattering of values
     # include the signed i32 minimum/maximum
-    @trans.should_receive(:write).with("\200\000\000\000").ordered
-    @trans.should_receive(:write).with("\377\376\037\r").ordered
-    @trans.should_receive(:write).with("\377\377\366\034").ordered
-    @trans.should_receive(:write).with("\377\377\377\375").ordered
-    @trans.should_receive(:write).with("\000\000\000\000").ordered
-    @trans.should_receive(:write).with("\000#\340\203").ordered
-    @trans.should_receive(:write).with("\000\0000+").ordered
-    @trans.should_receive(:write).with("\177\377\377\377").ordered
     [-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i|
       @prot.write_i32(i)
     end
     # try something out of signed range, it should clip
-    @trans.should_receive(:write).with("\200\000\000\005").ordered
-    @prot.write_i32(2 ** 31 + 5)
-    # lambda { @prot.write_i32(2 ** 65 + 5) }.should raise_error(RangeError)
+    @trans.read(1000).should == "\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377"
+    [2 ** 31 + 5, 2 ** 65 + 5].each do |i|
+      lambda { @prot.write_i32(i) }.should raise_error(RangeError)  
+    end
   end
-
+  
   it "should error gracefully when trying to write a nil i32" do
     lambda { @prot.write_i32(nil) }.should raise_error
   end
-
+  
   it "should write an i64" do
     # try a random scattering of values
     # try the signed i64 minimum/maximum
-    @trans.should_receive(:write).with("\200\000\000\000\000\000\000\000").ordered
-    @trans.should_receive(:write).with("\377\377\364\303\035\244+]").ordered
-    @trans.should_receive(:write).with("\377\377\377\377\376\231:\341").ordered
-    @trans.should_receive(:write).with("\377\377\377\377\377\377\377\026").ordered
-    @trans.should_receive(:write).with("\000\000\000\000\000\000\000\000").ordered
-    @trans.should_receive(:write).with("\000\000\000\000\000\000\004\317").ordered
-    @trans.should_receive(:write).with("\000\000\000\000\000#\340\204").ordered
-    @trans.should_receive(:write).with("\000\000\000\002\340\311~\365").ordered
-    @trans.should_receive(:write).with("\177\377\377\377\377\377\377\377").ordered
     [-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i|
       @prot.write_i64(i)
     end
     # try something out of signed range, it should clip
-    @trans.should_receive(:write).with("\200\000\000\000\000\000\000\005").ordered
-    @prot.write_i64(2**63 + 5)
-    # lambda { @prot.write_i64(2 ** 65 + 5) }.should raise_error(RangeError)
+    @trans.read(1000).should == ["\200\000\000\000\000\000\000\000",
+      "\377\377\364\303\035\244+]",
+      "\377\377\377\377\376\231:\341",
+      "\377\377\377\377\377\377\377\026",
+      "\000\000\000\000\000\000\000\000",
+      "\000\000\000\000\000\000\004\317",
+      "\000\000\000\000\000#\340\204",
+      "\000\000\000\002\340\311~\365",
+      "\177\377\377\377\377\377\377\377"].join("")
+    lambda { @prot.write_i64(2 ** 65 + 5) }.should raise_error(RangeError)
   end
-
+  
   it "should error gracefully when trying to write a nil i64" do
     lambda { @prot.write_i64(nil) }.should raise_error
   end
-
+  
   it "should write a double" do
     # try a random scattering of values, including min/max
-    @trans.should_receive(:write).with([Float::MIN].pack('G')).ordered
-    @trans.should_receive(:write).with("\300\223<\234\355\221hs").ordered
-    @trans.should_receive(:write).with("\300\376\0173\256\024z\341").ordered
-    @trans.should_receive(:write).with("\3007<2\336\372v\324").ordered
-    @trans.should_receive(:write).with("\000\000\000\000\000\000\000\000").ordered
-    @trans.should_receive(:write).with("@\310\037\220\365\302\217\\").ordered
-    @trans.should_receive(:write).with("@\200Y\327\n=p\244").ordered
-    @trans.should_receive(:write).with([Float::MAX].pack('G')).ordered
-    [Float::MIN, -1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX].each do |f|
+    values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX]
+    values.each do |f|
       @prot.write_double(f)
+      @trans.read(1000).should == [f].pack("G")
     end
   end
-
+  
   it "should error gracefully when trying to write a nil double" do
     lambda { @prot.write_double(nil) }.should raise_error
   end
-
+  
   it "should write a string" do
     str = "hello world"
-    @prot.should_receive(:write_i32).with(str.length).ordered
-    @trans.should_receive(:write).with(str).ordered
     @prot.write_string(str)
+    @trans.read(1000).should == [str.size].pack("N") + str
   end
-
+  
   it "should error gracefully when trying to write a nil string" do
     lambda { @prot.write_string(nil) }.should raise_error
   end
-
+  
   # message footer is a noop
-
+  
   it "should read a field header" do
-    @prot.should_receive(:read_byte).ordered.and_return(Thrift::Types::STRING)
-    @prot.should_receive(:read_i16).ordered.and_return(3)
+    @trans.write([Thrift::Types::STRING, 3].pack("cn"))
     @prot.read_field_begin.should == [nil, Thrift::Types::STRING, 3]
   end
-
+  
   # field footer is a noop
-
+  
   it "should read a stop field" do
-    @prot.should_receive(:read_byte).and_return(Thrift::Types::STOP)
-    @prot.should_not_receive(:read_i16)
+    @trans.write([Thrift::Types::STOP].pack("c"));
     @prot.read_field_begin.should == [nil, Thrift::Types::STOP, 0]
   end
 
   it "should read a map header" do
-    @prot.should_receive(:read_byte).and_return(Thrift::Types::DOUBLE, Thrift::Types::I64)
-    @prot.should_receive(:read_i32).and_return(42)
+    @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN"))
     @prot.read_map_begin.should == [Thrift::Types::DOUBLE, Thrift::Types::I64, 42]
   end
-
+  
   # map footer is a noop
-
+  
   it "should read a list header" do
-    @prot.should_receive(:read_byte).ordered.and_return(Thrift::Types::STRING)
-    @prot.should_receive(:read_i32).and_return(17)
+    @trans.write([Thrift::Types::STRING, 17].pack("cN"))
     @prot.read_list_begin.should == [Thrift::Types::STRING, 17]
   end
-
+  
   # list footer is a noop
-
+  
   it "should read a set header" do
-    @prot.should_receive(:read_byte).ordered.and_return(Thrift::Types::MAP)
-    @prot.should_receive(:read_i32).ordered.and_return(42)
-    @prot.read_set_begin.should == [Thrift::Types::MAP, 42]
+    @trans.write([Thrift::Types::STRING, 17].pack("cN"))
+    @prot.read_set_begin.should == [Thrift::Types::STRING, 17]
   end
-
+  
   # set footer is a noop
-
+  
   it "should read a bool" do
-    @prot.should_receive(:read_byte).and_return(1, 0)
+    @trans.write("\001\000");
     @prot.read_bool.should == true
     @prot.read_bool.should == false
   end
-
+  
   it "should read a byte" do
-    # try a scattering of values, including min/max
-    @trans.should_receive(:read_all).with(1).and_return(
-      "\200", "\307", "\375",
-      "\000", "\021", "\030", "\177"
-    )
     [-128, -57, -3, 0, 17, 24, 127].each do |i|
+      @trans.write([i].pack("c"))
       @prot.read_byte.should == i
     end
   end
-
+  
   it "should read an i16" do
     # try a scattering of values, including min/max
-    @trans.should_receive(:read_all).with(2).and_return(
-      "\200\000", "\353\213", "\376\237",
-      "\000\000", "\005\367", "\b\272", "\177\377"
-    )
     [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i|
+      @trans.write([i].pack("n"));
       @prot.read_i16.should == i
     end
   end
-
+  
   it "should read an i32" do
     # try a scattering of values, including min/max
-    @trans.should_receive(:read_all).with(4).and_return(
-      "\200\000\000\000", "\377\374i\213", "\377\377\347\244",
-      "\000\000\000\000", "\000\000\t/", "\000\001\340\363", "\177\377\377\377"
-    )
     [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i|
+      @trans.write([i].pack("N"))
       @prot.read_i32.should == i
     end
   end
-
+  
   it "should read an i64" do
     # try a scattering of values, including min/max
-    @trans.should_receive(:read_all).with(8).and_return(
-      "\200\000\000\000\000\000\000\000", "\377\377\377\377\370\243Z\b",
-      "\377\377\377\377\377\377\3476", "\000\000\000\000\000\000\000\000",
-      "\000\000\000\000\000\000\000 ", "\000\000\000\000\213\332\t\223",
-      "\177\377\377\377\377\377\377\377"
-    )
     [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i|
+      @trans.write([i >> 32, i & 0xFFFFFFFF].pack("NN"))
       @prot.read_i64.should == i
     end
   end
-
+  
   it "should read a double" do
     # try a random scattering of values, including min/max
-    @trans.should_receive(:read_all).with(8).and_return(
-      [Float::MIN].pack('G'), "\301\f9\370\374\362\317\226",
-      "\300t3\274x \243\016", "\000\000\000\000\000\000\000\000", "@^\317\fCo\301Y",
-      "AA\360A\217\317@\260", [Float::MAX].pack('G')
-    )
     [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f|
+      @trans.write([f].pack("G"));
       @prot.read_double.should == f
     end
   end
-
+  
   it "should read a string" do
     str = "hello world"
-    @prot.should_receive(:read_i32).and_return(str.length)
-    @trans.should_receive(:read_all).with(str.length).and_return(str)
+    @trans.write([str.size].pack("N") + str)
     @prot.read_string.should == str
   end
 end