Update Thrift CPP libraries to work with new generated source, change underlying buffers to use uint8_t* instead of std::string

Summary: Major overhaul to the CPP libraries.

Reviewed By: aditya

Test Plan: Again, keep an eye out for the unit tests commit

Notes: Initial perf tests show that Thrift is not only more robust than Pillar, but its implementation is actually around 10-20% faster. We can do about 10 RPC function calls with small data payloads in under 2ms. THAT IS FAST. THAT IS THRIFTY.




git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664714 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/protocol/TBinaryProtocol.cc b/lib/cpp/protocol/TBinaryProtocol.cc
index 4c10bab..1f31c8d 100644
--- a/lib/cpp/protocol/TBinaryProtocol.cc
+++ b/lib/cpp/protocol/TBinaryProtocol.cc
@@ -1,140 +1,246 @@
 #include "protocol/TBinaryProtocol.h"
-using namespace std;
+using std::string;
 
-string TBinaryProtocol::readFunction(TBuf& buf) const {
-  // Let readString increment the buffer position
-  return readString(buf);
+uint32_t TBinaryProtocol::writeStructBegin(TTransport* out,
+                                           const string& name) const {
+  return 0;
 }
 
-string TBinaryProtocol::writeFunction(const string& name,
-                                      const string& args) const{
-  return writeString(name) + args;
+uint32_t TBinaryProtocol::writeStructEnd(TTransport* out) const {
+  return 0;
 }
 
-map<uint32_t, TBuf> TBinaryProtocol::readStruct(TBuf& buf) const {
-  map<uint32_t, TBuf> fieldMap;
+uint32_t TBinaryProtocol::writeFieldBegin(TTransport* out,
+                                          const string& name,
+                                          const TType fieldType,
+                                          const uint16_t fieldId) const {
+  return
+    writeByte(out, (uint8_t)fieldType) +
+    writeU32(out, (uint32_t)fieldId);
+}
+
+uint32_t TBinaryProtocol::writeFieldEnd(TTransport* out) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::writeFieldStop(TTransport* out) const {
+  return
+    writeByte(out, (uint8_t)T_STOP);
+}  
+                               
+uint32_t TBinaryProtocol::writeMapBegin(TTransport* out,
+                                        const TType keyType,
+                                        const TType valType,
+                                        const uint32_t size) const {
+  return
+    writeByte(out, (uint8_t)keyType) +
+    writeByte(out, (uint8_t)valType) +
+    writeU32(out, size);
+}
+
+uint32_t TBinaryProtocol::writeMapEnd(TTransport* out) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::writeListBegin(TTransport* out,
+                                         const TType elemType,
+                                         const uint32_t size) const {
+  return
+    writeByte(out, (uint8_t) elemType) +
+    writeU32(out, size);
+}
+
+uint32_t TBinaryProtocol::writeListEnd(TTransport* out) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::writeSetBegin(TTransport* out,
+                                        const TType elemType,
+                                        const uint32_t size) const {
+  return
+    writeByte(out, (uint8_t)elemType) +
+    writeU32(out, size);
+}
+
+uint32_t TBinaryProtocol::writeSetEnd(TTransport* out) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::writeByte(TTransport* out,
+                                    const uint8_t byte) const {
+  out->write(&byte, 1);
+  return 1;
+}
+
+uint32_t TBinaryProtocol::writeU32(TTransport* out,
+                                   const uint32_t u32) const {
+  uint32_t net = (uint32_t)htonl(u32);
+  out->write((uint8_t*)&net, 4);
+  return 4;
+}
+
+uint32_t TBinaryProtocol::writeI32(TTransport* out,
+                                   const int32_t i32) const {
+  int32_t net = (int32_t)htonl(i32);
+  out->write((uint8_t*)&net, 4);
+  return 4;
+}
+
+uint32_t TBinaryProtocol::writeU64(TTransport* out,
+                                   const uint64_t u64) const {
+  uint64_t net = (uint64_t)htonll(u64);
+  out->write((uint8_t*)&net, 8);
+  return 8;
+}
+
+uint32_t TBinaryProtocol::writeI64(TTransport* out,
+                                   const int64_t i64) const {
+  int64_t net = (int64_t)htonll(i64);
+  out->write((uint8_t*)&net, 8);
+  return 8;
+}
+
+uint32_t TBinaryProtocol::writeString(TTransport* out,
+                                      const string& str) const {
+  uint32_t result = writeU32(out, str.size());
+  out->write((uint8_t*)str.data(), str.size());
+  return result + str.size();
+}
+
+/**
+ * Reading functions
+ */
+
+uint32_t TBinaryProtocol::readStructBegin(TTransport* in,
+                                          string& name) const {
+  name = "";
+  return 0;
+}
+
+uint32_t TBinaryProtocol::readStructEnd(TTransport* in) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::readFieldBegin(TTransport* in,
+                                         string& name,
+                                         TType& fieldType,
+                                         uint16_t& fieldId) const {
+  uint32_t result = 0;
+  uint8_t type;
+  result += readByte(in, type);
+  fieldType = (TType)type;
+  if (fieldType == T_STOP) {
+    fieldId = 0;
+    return result;
+  }
+  uint32_t id;
+  result += readU32(in, id);
+  fieldId = (uint16_t)id;
+  return result;
+}
   
-  if (buf.len < 4) {
-    return fieldMap;
-  }
-  uint32_t total_size = readU32(buf);
-  if (buf.len < total_size) {
-    // Data looks corrupt, we don't have that much, we will try to read what
-    // we can but be sure not to go over
-    total_size = buf.len;
-  }
-
-  // Field headers are 8 bytes, 4 byte fid + 4 byte length
-  while (total_size > 0 && buf.len > 8) {
-    uint32_t fid  = readU32(buf);
-    uint32_t flen = readU32(buf);
-    if (flen > buf.len) {
-      // flen corrupt, there isn't that much data left
-      break;
-    }
-    fieldMap.insert(make_pair(fid, TBuf(buf.data, flen)));
-    buf.data += flen;
-    buf.len  -= flen;
-    total_size -= 8 + flen;
-  }
-
-  return fieldMap;
+uint32_t TBinaryProtocol::readFieldEnd(TTransport* in) const {
+  return 0;
 }
-
-string TBinaryProtocol::writeStruct(const map<uint32_t,string>& s) const {
-  string result = "";
-  map<uint32_t,string>::const_iterator s_iter;
-  for (s_iter = s.begin(); s_iter != s.end(); ++s_iter) {
-    result += writeU32(s_iter->first);
-    result += writeU32(s_iter->second.size());
-    result += s_iter->second;
-  }
-  return writeU32(result.size()) + result;
-}
-
-string TBinaryProtocol::readString(TBuf& buf) const {
-  uint32_t len = readU32(buf);
-  if (len == 0) {
-    return "";
-  }
-  string result((const char*)(buf.data), len);
-  buf.data += len;
-  buf.len  -= len;
+ 
+uint32_t TBinaryProtocol::readMapBegin(TTransport* in,
+                                       TType& keyType,
+                                       TType& valType,
+                                       uint32_t& size) const {
+  uint8_t k, v;
+  uint32_t result = 0;
+  result += readByte(in, k);
+  keyType = (TType)k;
+  result += readByte(in, v);
+  valType = (TType)v;
+  result += readU32(in, size);
   return result;
 }
 
-uint8_t TBinaryProtocol::readByte(TBuf& buf) const {
-  if (buf.len == 0) {
-    return 0;
-  }
-  uint8_t result = (uint8_t)buf.data[0];
-  buf.data += 1;
-  buf.len  -= 1;
+uint32_t TBinaryProtocol::readMapEnd(TTransport* in) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::readListBegin(TTransport* in,
+                                        TType& elemType,
+                                        uint32_t& size) const {
+  uint8_t e;
+  uint32_t result = 0;
+  result += readByte(in, e);
+  elemType = (TType)e;
+  result += readU32(in, size);
   return result;
 }
 
-uint32_t TBinaryProtocol::readU32(TBuf& buf) const {
-  if (buf.len < 4) {
-    return 0;
-  }
-  uint32_t result = *(uint32_t*)buf.data;
-  buf.data += 4;
-  buf.len  -= 4;
+uint32_t TBinaryProtocol::readListEnd(TTransport* in) const {
+  return 0;
+}
+
+uint32_t TBinaryProtocol::readSetBegin(TTransport* in,
+                                       TType& elemType,
+                                       uint32_t& size) const {
+  uint8_t e;
+  uint32_t result = 0;
+  result += readByte(in, e);
+  elemType = (TType)e;
+  result += readU32(in, size);
   return result;
 }
 
-int32_t TBinaryProtocol::readI32(TBuf& buf) const {
-  if (buf.len < 4) {
-    return 0;
-  }
-  int32_t result = *(int32_t*)buf.data;
-  buf.data += 4;
-  buf.len  -= 4;
-  return result; 
+uint32_t TBinaryProtocol::readSetEnd(TTransport* in) const {
+  return 0;
 }
 
-uint64_t TBinaryProtocol::readU64(TBuf& buf) const {
-  if (buf.len < 8) {
-    return 0;
-  }
-  uint64_t result = *(uint64_t*)buf.data;
-  buf.data += 8;
-  buf.len  -= 8;
-  return result;
+uint32_t TBinaryProtocol::readByte(TTransport* in,
+                                   uint8_t& byte) const {
+  uint8_t b[1];
+  in->readAll(b, 1);
+  byte = *(uint8_t*)b;
+  return 1;
 }
 
-int64_t TBinaryProtocol::readI64(TBuf& buf) const {
-  if (buf.len < 8) {
-    return 0;
-  }
-  int64_t result = *(int64_t*)buf.data;
-  buf.data += 8;
-  buf.len  -= 8;
-  return result;
+uint32_t TBinaryProtocol::readU32(TTransport* in,
+                                  uint32_t& u32) const {
+  uint8_t b[4];
+  in->readAll(b, 4);
+  u32 = *(uint32_t*)b;
+  u32 = (uint32_t)ntohl(u32);
+  return 4;
 }
 
-string TBinaryProtocol::writeString(const string& str) const {
-  uint32_t size = str.size();
-  string result = string((const char*)&size, 4);
-  return result + str;
+uint32_t TBinaryProtocol::readI32(TTransport* in,
+                                  int32_t& i32) const {
+  uint8_t b[4];
+  in->readAll(b, 4);
+  i32 = *(int32_t*)b;
+  i32 = (int32_t)ntohl(i32);
+  return 4;
 }
 
-string TBinaryProtocol::writeByte(const uint8_t byte) const {
-  return string((const char*)&byte, 1);
+uint32_t TBinaryProtocol::readU64(TTransport* in,
+                                  uint64_t& u64) const {
+  uint8_t b[8];
+  in->readAll(b, 8);
+  u64 = *(uint64_t*)b;
+  u64 = (uint64_t)ntohll(u64);
+  return 8;
 }
 
-string TBinaryProtocol::writeU32(const uint32_t u32) const {
-  return string((const char*)&u32, 4);
+uint32_t TBinaryProtocol::readI64(TTransport* in,
+                                  int64_t& i64) const {
+  uint8_t b[8];
+  in->readAll(b, 8);
+  i64 = *(int64_t*)b;
+  i64 = (int64_t)ntohll(i64);
+  return 8;
 }
 
-string TBinaryProtocol::writeI32(int32_t i32) const {
-  return string((const char*)&i32, 4);
-}
-
-string TBinaryProtocol::writeU64(uint64_t u64) const {
-  return string((const char*)&u64, 8);
-}
-
-string TBinaryProtocol::writeI64(int64_t i64) const {
-  return string((const char*)&i64, 8);
+uint32_t TBinaryProtocol::readString(TTransport* in,
+                                     string& str) const {
+  uint32_t size, result;
+  result = readU32(in, size);
+  uint8_t b[size];
+  in->readAll(b, size);
+  str = string((char*)b, size);
+  return result+size;
 }
diff --git a/lib/cpp/protocol/TBinaryProtocol.h b/lib/cpp/protocol/TBinaryProtocol.h
index 976c383..e05bd9f 100644
--- a/lib/cpp/protocol/TBinaryProtocol.h
+++ b/lib/cpp/protocol/TBinaryProtocol.h
@@ -14,29 +14,114 @@
   TBinaryProtocol() {}
   ~TBinaryProtocol() {}
 
-  std::string
-    readFunction(TBuf& buf) const;
-  std::string
-    writeFunction(const std::string& name, const std::string& args) const;
+  /**
+   * Writing functions.
+   */
 
-  std::map<uint32_t, TBuf>
-    readStruct(TBuf& buf) const;
-  std::string
-    writeStruct(const std::map<uint32_t,std::string>& s) const;
+  uint32_t writeStructBegin   (TTransport*    out,
+                               const std::string& name)   const;
 
-  std::string readString  (TBuf& buf) const;
-  uint8_t     readByte    (TBuf& buf) const;
-  uint32_t    readU32     (TBuf& buf) const;
-  int32_t     readI32     (TBuf& buf) const;
-  uint64_t    readU64     (TBuf& buf) const;
-  int64_t     readI64     (TBuf& buf) const;
+  uint32_t writeStructEnd     (TTransport*    out)        const;
 
-  std::string writeString (const std::string& str) const;
-  std::string writeByte   (const uint8_t  byte)    const;
-  std::string writeU32    (const uint32_t u32)     const;
-  std::string writeI32    (const int32_t  i32)     const;
-  std::string writeU64    (const uint64_t u64)     const;
-  std::string writeI64    (const int64_t  i64)     const;
+  uint32_t writeFieldBegin    (TTransport*    out,
+                               const std::string& name,
+                               const TType    fieldType,
+                               const uint16_t fieldId)    const;
+
+  uint32_t writeFieldEnd      (TTransport*    out)        const;
+
+  uint32_t writeFieldStop     (TTransport*    out)        const;
+                                       
+  uint32_t writeMapBegin      (TTransport*    out,
+                               const TType    keyType,
+                               const TType    valType,
+                               const uint32_t size)       const;
+
+  uint32_t writeMapEnd        (TTransport*    out)        const;
+
+  uint32_t writeListBegin     (TTransport*    out,
+                               const TType    elemType,
+                               const uint32_t size)       const;
+
+  uint32_t writeListEnd       (TTransport*    out)        const;
+
+  uint32_t writeSetBegin      (TTransport*    out,
+                               const TType    elemType,
+                               const uint32_t size)       const;
+
+  uint32_t writeSetEnd        (TTransport*    out)        const;
+
+  uint32_t writeByte          (TTransport*    out,
+                               const uint8_t  byte)       const;
+
+  uint32_t writeU32           (TTransport*    out,
+                               const uint32_t u32)        const;
+
+  uint32_t writeI32           (TTransport*    out,
+                               const int32_t  i32)        const;
+
+  uint32_t writeU64           (TTransport*    out,
+                               const uint64_t u64)        const;
+
+  uint32_t writeI64           (TTransport*    out,
+                               const int64_t  i64)        const;
+
+  uint32_t writeString        (TTransport*    out,
+                               const std::string& str)    const;
+
+  /**
+   * Reading functions
+   */
+
+  uint32_t readStructBegin    (TTransport*    in,
+                               std::string& name)         const;
+
+  uint32_t readStructEnd      (TTransport*    in)         const;
+
+  uint32_t readFieldBegin     (TTransport*    in,
+                               std::string&   name,
+                               TType&         fieldType,
+                               uint16_t&      fieldId)    const;
+  
+  uint32_t readFieldEnd       (TTransport*    in)         const;
+ 
+  uint32_t readMapBegin       (TTransport*    in,
+                               TType&         keyType,
+                               TType&         valType,
+                               uint32_t&      size)       const;
+
+  uint32_t readMapEnd         (TTransport*    in)         const;
+
+  uint32_t readListBegin      (TTransport*    in,
+                               TType&         elemType,
+                               uint32_t&      size)       const;
+  
+  uint32_t readListEnd        (TTransport*    in)         const;
+
+  uint32_t readSetBegin       (TTransport*    in,
+                               TType&         elemType,
+                               uint32_t&      size)       const;
+
+  uint32_t readSetEnd         (TTransport*    in)         const;
+
+  uint32_t readByte           (TTransport*    in,
+                               uint8_t&       byte)       const;
+
+  uint32_t readU32            (TTransport*    in,
+                               uint32_t&      u32)        const;
+
+  uint32_t readI32            (TTransport*    in,
+                               int32_t&       i32)        const;
+
+  uint32_t readU64            (TTransport*    in,
+                               uint64_t&      u64)        const;
+
+  uint32_t readI64            (TTransport*    in,
+                               int64_t&       i64)        const;
+
+  uint32_t readString         (TTransport*    in,
+                               std::string&   str)        const;
+
 };
 
 #endif
diff --git a/lib/cpp/protocol/TProtocol.h b/lib/cpp/protocol/TProtocol.h
index 1f2e0c8..fe2d6ef 100644
--- a/lib/cpp/protocol/TProtocol.h
+++ b/lib/cpp/protocol/TProtocol.h
@@ -1,14 +1,42 @@
 #ifndef T_PROTOCOL_H
 #define T_PROTOCOL_H
 
+#include <netinet/in.h>
 #include <sys/types.h>
 #include <string>
 #include <map>
 
+#include "transport/TTransport.h"
+
+#define ntohll(x) (((uint64_t)(ntohl((int)((x << 32) >> 32))) << 32) | (uint32_t)ntohl(((int)(x >> 32))))
+
+#define htonll(x) ntohll(x)
+
 /** Forward declaration for TProtocol */
 struct TBuf;
 
 /**
+ * Enumerated definition of the types that the Thrift protocol supports.
+ * Take special note of the T_END type which is used specifically to mark
+ * the end of a sequence of fields.
+ */
+enum TType {
+  T_STOP       = 1,
+  T_BYTE       = 2,
+  T_U16        = 3,
+  T_I16        = 4,
+  T_U32        = 5,
+  T_I32        = 6,
+  T_U64        = 7,
+  T_I64        = 8,
+  T_STRING     = 9,
+  T_STRUCT     = 10,
+  T_MAP        = 11,
+  T_SET        = 12,
+  T_LIST       = 13
+};
+
+/**
  * Abstract class for a thrift protocol driver. These are all the methods that
  * a protocol must implement. Essentially, there must be some way of reading
  * and writing all the base types, plus a mechanism for writing out structs
@@ -25,64 +53,211 @@
   virtual ~TProtocol() {}
 
   /**
-   * Function call serialization.
+   * Writing functions.
    */
 
-  virtual std::string
-    readFunction(TBuf& buf) const = 0;
-  virtual std::string
-    writeFunction(const std::string& name, const std::string& args) const = 0;
+  virtual uint32_t writeStructBegin   (TTransport*    out,
+                                       const std::string& name)   const = 0;
+
+  virtual uint32_t writeStructEnd     (TTransport*    out)        const = 0;
+
+  virtual uint32_t writeFieldBegin    (TTransport*    out,
+                                       const std::string& name,
+                                       const TType    fieldType,
+                                       const uint16_t fieldId)    const = 0;
+
+  virtual uint32_t writeFieldEnd      (TTransport*    out)        const = 0;
+
+  virtual uint32_t writeFieldStop     (TTransport*    out)        const = 0;
+                                      
+  virtual uint32_t writeMapBegin      (TTransport*    out,
+                                       const TType    keyType,
+                                       const TType    valType,
+                                       const uint32_t size)       const = 0;
+
+  virtual uint32_t writeMapEnd        (TTransport*    out)        const = 0;
+
+  virtual uint32_t writeListBegin     (TTransport*    out,
+                                       const TType    elemType,
+                                       const uint32_t size)       const = 0;
+
+  virtual uint32_t writeListEnd       (TTransport*    out)        const = 0;
+
+  virtual uint32_t writeSetBegin      (TTransport*    out,
+                                       const TType    elemType,
+                                       const uint32_t size)       const = 0;
+
+  virtual uint32_t writeSetEnd        (TTransport*    out)        const = 0;
+
+  virtual uint32_t writeByte          (TTransport*    out,
+                                       const uint8_t  byte)       const = 0;
+
+  virtual uint32_t writeU32           (TTransport*    out,
+                                       const uint32_t u32)        const = 0;
+
+  virtual uint32_t writeI32           (TTransport*    out,
+                                       const int32_t  i32)        const = 0;
+
+  virtual uint32_t writeU64           (TTransport*    out,
+                                       const uint64_t u64)        const = 0;
+
+  virtual uint32_t writeI64           (TTransport*    out,
+                                       const int64_t  i64)        const = 0;
+
+  virtual uint32_t writeString        (TTransport*    out,
+                                       const std::string& str)    const = 0;
 
   /**
-   * Struct serialization.
+   * Reading functions
    */
 
-  virtual std::map<uint32_t, TBuf>
-    readStruct(TBuf& buf) const = 0;
-  virtual std::string
-    writeStruct(const std::map<uint32_t,std::string>& s) const = 0;
+  virtual uint32_t readStructBegin    (TTransport*    in,
+                                       std::string& name)         const = 0;
+
+  virtual uint32_t readStructEnd      (TTransport*    in)         const = 0;
+
+  virtual uint32_t readFieldBegin     (TTransport*    in,
+                                       std::string&   name,
+                                       TType&         fieldType,
+                                       uint16_t&      fieldId)    const = 0;
+  
+  virtual uint32_t readFieldEnd       (TTransport*    in)         const = 0;
+ 
+  virtual uint32_t readMapBegin       (TTransport*    in,
+                                       TType&         keyType,
+                                       TType&         valType,
+                                       uint32_t&      size)       const = 0;
+
+  virtual uint32_t readMapEnd         (TTransport*    in)         const = 0;
+
+  virtual uint32_t readListBegin      (TTransport*    in,
+                                       TType&         elemType,
+                                       uint32_t&      size)       const = 0;
+
+  virtual uint32_t readListEnd        (TTransport*    in)         const = 0;
+
+  virtual uint32_t readSetBegin       (TTransport*    in,
+                                       TType&         elemType,
+                                       uint32_t&      size)       const = 0;
+
+  virtual uint32_t readSetEnd         (TTransport*    in)         const = 0;
+
+  virtual uint32_t readByte           (TTransport*    in,
+                                       uint8_t&       byte)       const = 0;
+
+  virtual uint32_t readU32            (TTransport*    in,
+                                       uint32_t&      u32)        const = 0;
+
+  virtual uint32_t readI32            (TTransport*    in,
+                                       int32_t&       i32)        const = 0;
+
+  virtual uint32_t readU64            (TTransport*    in,
+                                       uint64_t&      u64)        const = 0;
+
+  virtual uint32_t readI64            (TTransport*    in,
+                                       int64_t&       i64)        const = 0;
+
+  virtual uint32_t readString         (TTransport*    in,
+                                       std::string&   str)        const = 0;
 
   /**
-   * Basic data type deserialization. Note that these read methods do not
-   * take a const reference to the TBuf object. They SHOULD change the TBuf
-   * object so that it reflects the buffer AFTER the basic data type has
-   * been consumed such that data may continue being read serially from the
-   * buffer.
+   * Method to arbitrarily skip over data.
    */
-
-  virtual std::string readString  (TBuf& buf) const = 0;
-  virtual uint8_t     readByte    (TBuf& buf) const = 0;
-  virtual uint32_t    readU32     (TBuf& buf) const = 0;
-  virtual int32_t     readI32     (TBuf& buf) const = 0;
-  virtual uint64_t    readU64     (TBuf& buf) const = 0;
-  virtual int64_t     readI64     (TBuf& buf) const = 0;
-
-  virtual std::string writeString (const std::string& str) const = 0;
-  virtual std::string writeByte   (const uint8_t  byte)    const = 0;
-  virtual std::string writeU32    (const uint32_t u32)     const = 0;
-  virtual std::string writeI32    (const int32_t  i32)     const = 0;
-  virtual std::string writeU64    (const uint64_t u64)     const = 0;
-  virtual std::string writeI64    (const int64_t  i64)     const = 0;
+  uint32_t skip(TTransport* in, TType type) const {
+    switch (type) {
+    case T_BYTE:
+      {
+        uint8_t byte;
+        return readByte(in, byte);
+      }
+    case T_U32:
+      {
+        uint32_t u32;
+        return readU32(in, u32);
+      }
+    case T_I32:
+      {
+        int32_t i32;
+        return readI32(in, i32);
+      }
+    case T_U64:
+      {
+        uint64_t u64;
+        return readU64(in, u64);
+      }
+    case T_I64:
+      {
+        int64_t i64;
+        return readI64(in, i64);
+      }
+    case T_STRING:
+      {
+        std::string str;
+        return readString(in, str);
+      }
+    case T_STRUCT:
+      {
+        uint32_t result = 0;
+        std::string name;
+        uint16_t fid;
+        TType ftype;
+        result += readStructBegin(in, name);
+        while (true) {
+          result += readFieldBegin(in, name, ftype, fid);
+          if (ftype == T_STOP) {
+            break;
+          }
+          result += skip(in, ftype);
+          result += readFieldEnd(in);
+        }
+        result += readStructEnd(in);
+        return result;
+      }
+    case T_MAP:
+      {
+        uint32_t result = 0;
+        TType keyType;
+        TType valType;
+        uint32_t i, size;
+        result += readMapBegin(in, keyType, valType, size);
+        for (i = 0; i < size; i++) {
+          result += skip(in, keyType);
+          result += skip(in, valType);
+        }
+        result += readMapEnd(in);
+        return result;
+      }
+    case T_SET:
+      {
+        uint32_t result = 0;
+        TType elemType;
+        uint32_t i, size;
+        result += readSetBegin(in, elemType, size);
+        for (i = 0; i < size; i++) {
+          result += skip(in, elemType);
+        }
+        result += readSetEnd(in);
+        return result;
+      }
+    case T_LIST:
+      {
+        uint32_t result = 0;
+        TType elemType;
+        uint32_t i, size;
+        result += readListBegin(in, elemType, size);
+        for (i = 0; i < size; i++) {
+          result += skip(in, elemType);
+        }
+        result += readListEnd(in);
+        return result;
+      }
+    default:
+      return 0;
+    }
+  }
 
  protected:
   TProtocol() {}
 };
 
-/**
- * Wrapper around raw data that allows us to track the length of a data
- * buffer. It is the responsibility of a robust TProtocol implementation
- * to ensure that any reads that are done from data do NOT overrun the
- * memory address at data+len. It is also a convention that TBuf objects
- * do NOT own the memory pointed to by data. They are merely wrappers
- * around buffers that have been allocated elsewhere. Therefore, the user
- * should never allocate memory before putting it into a TBuf nor should
- * they free the data pointed to by a TBuf.
- */
-struct TBuf {
-  TBuf(const TBuf& that) : data(that.data), len(that.len) {}
-  TBuf(const uint8_t* d, uint32_t l) : data(d), len(l) {}
-  const uint8_t* data;
-  uint32_t len;
-};
-
 #endif