You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by jk...@apache.org on 2018/04/08 11:11:42 UTC

[thrift] branch master updated: THRIFT-3773: Swift 3 changes, Squashed (#1084)

This is an automated email from the ASF dual-hosted git repository.

jking pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/thrift.git


The following commit(s) were added to refs/heads/master by this push:
     new a9b6c70  THRIFT-3773: Swift 3 changes, Squashed (#1084)
a9b6c70 is described below

commit a9b6c7039b3f61b03528d262c3e8d9dc022e89cd
Author: Chris Simpson <ap...@gmail.com>
AuthorDate: Sun Apr 8 07:11:37 2018 -0400

    THRIFT-3773: Swift 3 changes, Squashed (#1084)
    
    Client: swift
---
 Thrift-swift3.podspec                              |   16 +
 .../cpp/src/thrift/generate/t_swift_generator.cc   | 2004 +++++++++++++++-----
 lib/swift/Package.swift                            |   24 +
 lib/swift/README.md                                |  215 +++
 lib/swift/Sources/LinuxHelper.swift                |   46 +
 lib/swift/Sources/TApplicationError.swift          |  157 ++
 lib/swift/Sources/TBinary.swift                    |   32 +
 lib/swift/Sources/TBinaryProtocol.swift            |  384 ++++
 lib/swift/Sources/TClient.swift                    |   55 +
 lib/swift/Sources/TCompactProtocol.swift           |  575 ++++++
 lib/swift/Sources/TEnum.swift                      |   32 +
 lib/swift/Sources/TError.swift                     |   77 +
 lib/swift/Sources/TFileHandleTransport.swift       |   56 +
 lib/swift/Sources/TFileTransport.swift             |  101 +
 lib/swift/Sources/TFramedTransport.swift           |  123 ++
 lib/swift/Sources/THTTPSessionTransport.swift      |  184 ++
 lib/swift/Sources/TList.swift                      |  138 ++
 lib/swift/Sources/TMap.swift                       |  194 ++
 lib/swift/Sources/TMemoryBufferTransport.swift     |   74 +
 lib/swift/Sources/TMultiplexedProtocol.swift       |   47 +
 lib/swift/Sources/TProcessor.swift                 |   29 +
 lib/swift/Sources/TProtocol.swift                  |  182 ++
 lib/swift/Sources/TProtocolError.swift             |  146 ++
 lib/swift/Sources/TSSLSocketTransport.swift        |  229 +++
 lib/swift/Sources/TSSLSocketTransportError.swift   |   48 +
 lib/swift/Sources/TSerializable.swift              |  136 ++
 lib/swift/Sources/TSet.swift                       |  189 ++
 lib/swift/Sources/TSocketServer.swift              |  149 ++
 lib/swift/Sources/TSocketTransport.swift           |  210 ++
 lib/swift/Sources/TStreamTransport.swift           |  143 ++
 lib/swift/Sources/TStruct.swift                    |  100 +
 lib/swift/Sources/TTransport.swift                 |   64 +
 lib/swift/Sources/TTransportError.swift            |   86 +
 lib/swift/Sources/TWrappedProtocol.swift           |  208 ++
 lib/swift/Sources/Thrift.swift                     |    3 +
 lib/swift/Tests/LinuxMain.swift                    |    8 +
 .../Tests/ThriftTests/TBinaryProtocolTests.swift   |  146 ++
 .../Tests/ThriftTests/TCompactProtocolTests.swift  |  144 ++
 lib/swift/Tests/ThriftTests/ThriftTests.swift      |   18 +
 39 files changed, 6262 insertions(+), 510 deletions(-)

diff --git a/Thrift-swift3.podspec b/Thrift-swift3.podspec
new file mode 100644
index 0000000..e13d171
--- /dev/null
+++ b/Thrift-swift3.podspec
@@ -0,0 +1,16 @@
+Pod::Spec.new do |s|
+  s.name         = "Thrift-swift3"
+  s.version      = "1.1.0"
+  s.summary       = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC."
+  s.description   = <<-DESC
+The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.
+                    DESC
+  s.homepage      = "http://thrift.apache.org"
+  s.license       = { :type => 'Apache License, Version 2.0', :url => 'https://raw.github.com/apache/thrift/thrift-0.9.0/LICENSE' }
+  s.author        = { "The Apache Software Foundation" => "apache@apache.org" }
+  s.ios.deployment_target = '9.0'
+  s.osx.deployment_target = '10.10'
+  s.requires_arc  = true
+  s.source        = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-1.0.0" }
+  s.source_files  = "lib/swift/Sources/*.swift"
+end
diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
index 7b4d224..b6bf7e4 100644
--- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc
@@ -41,9 +41,9 @@ using std::vector;
 static const string endl = "\n"; // avoid ostream << std::endl flushes
 
 /**
- * Swift code generator.
+ * Swift 3 code generator.
  *
- * Designed from the Objective-C (aka Cocoa) generator.
+ * Designed from the Swift/Cocoa code generator(s)
  */
 class t_swift_generator : public t_oop_generator {
 public:
@@ -56,18 +56,33 @@ public:
 
     log_unexpected_ = false;
     async_clients_ = false;
-    promise_kit_ = false;
     debug_descriptions_ = false;
+    no_strict_ = false;
+    namespaced_ = false;
+    gen_cocoa_ = false;
+    promise_kit_ = false;
+    safe_enums_ = false;
 
     for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
       if( iter->first.compare("log_unexpected") == 0) {
         log_unexpected_ = true;
       } else if( iter->first.compare("async_clients") == 0) {
         async_clients_ = true;
-      } else if( iter->first.compare("promise_kit") == 0) {
-        promise_kit_ = true;
+      } else if( iter->first.compare("no_strict") == 0) {
+        no_strict_ = true;
       } else if( iter->first.compare("debug_descriptions") == 0) {
         debug_descriptions_ = true;
+      } else if( iter->first.compare("namespaced") == 0) {
+        namespaced_ = true;
+      } else if( iter->first.compare("cocoa") == 0) {
+        gen_cocoa_ = true;
+      } else if( iter->first.compare("safe_enums") == 0) {
+        safe_enums_ = true;
+      } else if( iter->first.compare("promise_kit") == 0) {
+        if (gen_cocoa_ == false) {
+          throw "PromiseKit only available with Swift 2.x, use `cocoa` option" + iter->first;
+        }
+        promise_kit_ = true;
       } else {
         throw "unknown option swift:" + iter->first;
       }
@@ -95,12 +110,7 @@ public:
   void generate_xception(t_struct* txception);
   void generate_service(t_service* tservice);
 
-  void print_const_value(ostream& out,
-                         string name,
-                         t_type* type,
-                         t_const_value* value,
-                         bool defval = false,
-                         bool is_property = false);
+
   void render_const_value(ostream& out,
                           t_type* type,
                           t_const_value* value);
@@ -108,6 +118,7 @@ public:
   void generate_swift_struct(ofstream& out,
                              t_struct* tstruct,
                              bool is_private);
+
   void generate_swift_struct_init(ofstream& out,
                                   t_struct* tstruct,
                                   bool all,
@@ -128,9 +139,10 @@ public:
                                               bool is_result,
                                               bool is_private);
   void generate_swift_struct_reader(ofstream& out, t_struct* tstruct, bool is_private);
-  void generate_swift_struct_writer(ofstream& out,t_struct* tstruct, bool is_private);
-  void generate_swift_struct_result_writer(ofstream& out, t_struct* tstruct);
+
+
   void generate_swift_struct_printable_extension(ofstream& out, t_struct* tstruct);
+  void generate_swift_union_reader(ofstream& out, t_struct* tstruct);
 
   string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
   string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
@@ -175,13 +187,40 @@ public:
   string declare_property(t_field* tfield, bool is_private);
   string function_signature(t_function* tfunction);
   string async_function_signature(t_function* tfunction);
-  string promise_function_signature(t_function* tfunction);
-  string function_name(t_function* tfunction);
+
+
   string argument_list(t_struct* tstruct, string protocol_name, bool is_internal);
   string type_to_enum(t_type* ttype, bool qualified=false);
   string maybe_escape_identifier(const string& identifier);
   void populate_reserved_words();
-
+  /** Swift 3 specific */
+  string enum_case_name(t_enum_value* tenum_case, bool declaration);
+  string enum_const_name(string enum_identifier);
+  void function_docstring(ofstream& out, t_function* tfunction);
+  void async_function_docstring(ofstream& out, t_function* tfunction);
+  void generate_docstring(ofstream& out, string& doc);
+
+  /** Swift 2/Cocoa carryover */
+  string promise_function_signature(t_function* tfunction);
+  string function_name(t_function* tfunction);
+  void generate_old_swift_struct_writer(ofstream& out,t_struct* tstruct, bool is_private);
+  void generate_old_swift_struct_result_writer(ofstream& out, t_struct* tstruct);
+
+  /** Swift 2/Cocoa backwards compatibility*/
+  void generate_old_enum(t_enum* tenum);
+  void generate_old_swift_struct(ofstream& out,
+                                 t_struct* tstruct,
+                                 bool is_private);
+  void generate_old_swift_service_client_async_implementation(ofstream& out,
+                                                              t_service* tservice);
+
+  static std::string get_real_swift_module(const t_program* program) {
+    std::string real_module = program->get_namespace("swift");
+    if (real_module.empty()) {
+      return program->get_name();
+    }
+    return real_module;
+  }
 private:
 
   void block_open(ostream& out) {
@@ -195,9 +234,15 @@ private:
     if (end_line) out << endl;
   }
 
-
   bool field_is_optional(t_field* tfield) {
-    return tfield->get_req() == t_field::T_OPTIONAL;
+    bool opt = tfield->get_req() == t_field::T_OPTIONAL;
+    if (tfield->annotations_.find("swift.nullable") != tfield->annotations_.end() && tfield->get_req() != t_field::T_REQUIRED) {
+      opt = true;
+    }
+    if (gen_cocoa_) { // Backwards compatibility, only if its actually "optional"
+      opt = tfield->get_req() == t_field::T_OPTIONAL;
+    }
+    return opt;
   }
 
   bool struct_has_required_fields(t_struct* tstruct) {
@@ -233,10 +278,17 @@ private:
 
   bool log_unexpected_;
   bool async_clients_;
-  bool promise_kit_;
-  bool debug_descriptions_;
 
+  bool debug_descriptions_;
+  bool no_strict_;
+  bool namespaced_;
+  bool safe_enums_;
   set<string> swift_reserved_words_;
+
+  /** Swift 2/Cocoa compatibility */
+  bool gen_cocoa_;
+  bool promise_kit_;
+
 };
 
 /**
@@ -245,13 +297,21 @@ private:
  */
 void t_swift_generator::init_generator() {
   // Make output directory
-  MKDIR(get_out_dir().c_str());
+  string module = get_real_swift_module(program_);
+  string out_dir = get_out_dir();
+  string module_path = out_dir;
+  string name = capitalize(program_name_);
+  if (namespaced_ && !module.empty()) {
+    module_path = module_path + "/" + module;
+    name = capitalize(module);
+  }
+  MKDIR(module_path.c_str());
 
   populate_reserved_words();
 
   // we have a .swift declarations file...
-  string f_decl_name = capitalize(program_name_) + ".swift";
-  string f_decl_fullname = get_out_dir() + f_decl_name;
+  string f_decl_name = name + ".swift";
+  string f_decl_fullname = module_path + "/" + f_decl_name;
   f_decl_.open(f_decl_fullname.c_str());
 
   f_decl_ << autogen_comment() << endl;
@@ -259,8 +319,8 @@ void t_swift_generator::init_generator() {
   f_decl_ << swift_imports() << swift_thrift_imports() << endl;
 
   // ...and a .swift implementation extensions file
-  string f_impl_name = capitalize(program_name_) + "+Exts.swift";
-  string f_impl_fullname = get_out_dir() + f_impl_name;
+  string f_impl_name = name + "+Exts.swift";
+  string f_impl_fullname = module_path + "/" + f_impl_name;
   f_impl_.open(f_impl_fullname.c_str());
 
   f_impl_ << autogen_comment() << endl;
@@ -286,6 +346,12 @@ string t_swift_generator::swift_imports() {
     includes << "import " << *i_iter << endl;
   }
 
+  if (namespaced_) {
+    const vector<t_program*>& program_includes = program_->get_includes();
+    for (size_t i = 0; i < program_includes.size(); ++i) {
+      includes << ("import " + get_real_swift_module(program_includes[i])) << endl;
+    }
+  }
   includes << endl;
 
   return includes.str();
@@ -301,7 +367,7 @@ string t_swift_generator::swift_thrift_imports() {
   vector<string> includes_list;
   includes_list.push_back("Thrift");
 
-  if (promise_kit_) {
+  if (gen_cocoa_ && promise_kit_) {
     includes_list.push_back("PromiseKit");
   }
 
@@ -337,14 +403,110 @@ void t_swift_generator::generate_typedef(t_typedef* ttypedef) {
   f_decl_ << endl;
 }
 
+
 /**
  * Generates code for an enumerated type. In Swift, this is
  * essentially the same as the thrift definition itself, using
- * Swift syntax.
+ * Swift syntax.  Conforms to TEnum which
+ * implementes read/write.
  *
  * @param tenum The enumeration
  */
 void t_swift_generator::generate_enum(t_enum* tenum) {
+  if (gen_cocoa_) {
+    generate_old_enum(tenum);
+    return;
+  }
+  f_decl_ << indent() << "public enum " << tenum->get_name() << " : TEnum";
+  block_open(f_decl_);
+
+  vector<t_enum_value*> constants = tenum->get_constants();
+  vector<t_enum_value*>::iterator c_iter;
+
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    f_decl_ << indent() << "case " << enum_case_name((*c_iter), true) << endl;
+  }
+
+  // unknown associated value case for safety and similar behavior to other languages
+  if (safe_enums_) {
+    f_decl_ << indent() << "case unknown(Int32)" << endl;
+  }
+  f_decl_ << endl;
+
+  // TSerializable read(from:)
+  f_decl_ << indent() << "public static func read(from proto: TProtocol) throws -> "
+          << tenum->get_name();
+  block_open(f_decl_);
+  f_decl_ << indent() << "let raw: Int32 = try proto.read()" << endl;
+  f_decl_ << indent() << "let new = " << tenum->get_name() << "(rawValue: raw)" << endl;
+
+  f_decl_ << indent() << "if let unwrapped = new {" << endl;
+  indent_up();
+  f_decl_ << indent() << "return unwrapped" << endl;
+  indent_down();
+  f_decl_ << indent() << "} else {" << endl;
+  indent_up();
+  f_decl_ << indent() << "throw TProtocolError(error: .invalidData," << endl;
+  f_decl_ << indent() << "                     message: \"Invalid enum value (\\(raw)) for \\("
+          << tenum->get_name() << ".self)\")" << endl;
+  indent_down();
+  f_decl_ << indent() << "}" << endl;
+  block_close(f_decl_);
+
+  // empty init for TSerializable
+  f_decl_ << endl;
+  f_decl_ << indent() << "public init()";
+  block_open(f_decl_);
+
+  f_decl_ << indent() << "self = ." << enum_case_name(constants.front(), false) << endl;
+  block_close(f_decl_);
+  f_decl_ << endl;
+
+  // rawValue getter
+  f_decl_ << indent() << "public var rawValue: Int32";
+  block_open(f_decl_);
+  f_decl_ << indent() << "switch self {" << endl;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    f_decl_ << indent() << "case ." << enum_case_name((*c_iter), true)
+            << ": return " << (*c_iter)->get_value() << endl;
+  }
+  if (safe_enums_) {
+    f_decl_ << indent() << "case .unknown(let value): return value" << endl;
+  }
+  f_decl_ << indent() << "}" << endl;
+  block_close(f_decl_);
+  f_decl_ << endl;
+
+  // convenience rawValue initalizer
+  f_decl_ << indent() << "public init?(rawValue: Int32)";
+  block_open(f_decl_);
+  f_decl_ << indent() << "switch rawValue {" << endl;;
+  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
+    f_decl_ << indent() << "case " << (*c_iter)->get_value()
+            << ": self = ." << enum_case_name((*c_iter), true) << endl;
+  }
+  if (!safe_enums_) {
+    f_decl_ << indent() << "default: return nil" << endl;
+  } else {
+    f_decl_ << indent() << "default: self = .unknown(rawValue)" << endl;
+  }
+  f_decl_ << indent() << "}" << endl;
+  block_close(f_decl_);
+
+
+
+
+  block_close(f_decl_);
+  f_decl_ << endl;
+}
+
+/**
+ * Generates code for an enumerated type. This is for Swift 2.x/Cocoa
+ * backwards compatibility
+ *
+ * @param tenum The enumeration
+ */
+void t_swift_generator::generate_old_enum(t_enum* tenum) {
   f_decl_ << indent() << "public enum " << tenum->get_name() << " : Int32";
   block_open(f_decl_);
 
@@ -385,6 +547,31 @@ void t_swift_generator::generate_enum(t_enum* tenum) {
   f_impl_ << endl;
 }
 
+string t_swift_generator::enum_case_name(t_enum_value* tenum_case, bool declaration) {
+  string name = tenum_case->get_name();
+  // force to lowercase for Swift style, maybe escape if its a keyword
+  std::transform(name.begin(), name.end(), name.begin(), ::tolower);
+  if (declaration) {
+    name = maybe_escape_identifier(name);
+  }
+  return name;
+}
+
+/**
+ * Renders a constant enum value by transforming the value portion to lowercase
+ * for Swift style.
+ */
+string t_swift_generator::enum_const_name(string enum_identifier) {
+  string::iterator it;
+  for (it = enum_identifier.begin(); it < enum_identifier.end(); ++it) {
+    if ((*it) == '.') {
+      break;
+    }
+  }
+  std::transform(it, enum_identifier.end(), it, ::tolower);
+  return enum_identifier;
+}
+
 /**
  * Generates public constants for all Thrift constants.
  *
@@ -425,7 +612,7 @@ void t_swift_generator::generate_struct(t_struct* tstruct) {
 }
 
 /**
- * Exceptions are structs, but they conform to ErrorType
+ * Exceptions are structs, but they conform to Error
  *
  * @param tstruct The struct definition
  */
@@ -434,6 +621,34 @@ void t_swift_generator::generate_xception(t_struct* txception) {
   generate_swift_struct_implementation(f_impl_, txception, false, false);
 }
 
+void t_swift_generator::generate_docstring(ofstream& out, string& doc) {
+  if (doc != "") {
+    std::vector<std::string> strings;
+
+    std::string::size_type pos = 0;
+    std::string::size_type prev = 0;
+    while (((pos = doc.find("\n", prev)) != std::string::npos)
+        || ((pos = doc.find("\r", prev)) != std::string::npos)
+        || ((pos = doc.find("\r\n", prev)) != std::string::npos))
+    {
+        strings.push_back(doc.substr(prev, pos - prev));
+        prev = pos + 1;
+    }
+
+    // To get the last substring (or only, if delimiter is not found)
+    strings.push_back(doc.substr(prev));
+
+    vector<string>::const_iterator d_iter;
+    for (d_iter = strings.begin(); d_iter != strings.end(); ++d_iter) {
+      if ((*d_iter) != "") {
+        out << indent() << "/// " << (*d_iter) << endl;
+      }
+    }
+  }
+}
+
+
+
 /**
  * Generate the interface for a struct. Only properties and
  * init methods are included.
@@ -446,6 +661,83 @@ void t_swift_generator::generate_swift_struct(ofstream& out,
                                               t_struct* tstruct,
                                               bool is_private) {
 
+  if (gen_cocoa_) {
+    generate_old_swift_struct(out, tstruct, is_private);
+    return;
+  }
+  string doc = tstruct->get_doc();
+  generate_docstring(out, doc);
+
+
+  // properties
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+
+  if (tstruct->is_union()) {
+    // special, unions
+    out << indent() << "public enum " << tstruct->get_name();
+    block_open(out);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << endl;
+      string doc = (*m_iter)->get_doc();
+      generate_docstring(out, doc);
+      out << indent() << "case "
+          << maybe_escape_identifier((*m_iter)->get_name()) << "(val: "
+          << type_name((*m_iter)->get_type(), false) << ")" << endl;
+    }
+  } else {
+    // Normal structs
+
+    string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
+
+    out << indent() << visibility << " final class " << tstruct->get_name();
+
+    if (tstruct->is_xception()) {
+      out << " : Swift.Error"; // Error seems to be a common exception name in thrift
+    }
+
+    block_open(out);
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      out << endl;
+      // TODO: Defaults
+
+      string doc = (*m_iter)->get_doc();
+      generate_docstring(out, doc);
+
+      out << indent() << declare_property(*m_iter, is_private) << endl;
+    }
+
+    out << endl;
+    out << endl;
+
+    if (!struct_has_required_fields(tstruct)) {
+      indent(out) << visibility << " init() { }" << endl;
+    }
+    if (struct_has_required_fields(tstruct)) {
+      generate_swift_struct_init(out, tstruct, false, is_private);
+    }
+    if (struct_has_optional_fields(tstruct)) {
+      generate_swift_struct_init(out, tstruct, true, is_private);
+    }
+  }
+
+  block_close(out);
+
+  out << endl;
+}
+
+/**
+ * Legacy Swift2/Cocoa generator
+ *
+ * @param tstruct
+ * @param is_private
+ */
+
+
+void t_swift_generator::generate_old_swift_struct(ofstream& out,
+                                                  t_struct* tstruct,
+                                                  bool is_private) {
   string visibility = is_private ? "private" : "public";
 
   out << indent() << visibility << " final class " << tstruct->get_name();
@@ -500,7 +792,7 @@ void t_swift_generator::generate_swift_struct_init(ofstream& out,
                                                    bool all,
                                                    bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
+  string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
 
   indent(out) << visibility << " init(";
 
@@ -526,9 +818,19 @@ void t_swift_generator::generate_swift_struct_init(ofstream& out,
   block_open(out);
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    if (all || (*m_iter)->get_req() == t_field::T_REQUIRED || (*m_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
-      out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = "
-          << maybe_escape_identifier((*m_iter)->get_name()) << endl;
+    if (!gen_cocoa_) {
+      bool should_set = all;
+      should_set = should_set || !field_is_optional((*m_iter));
+      if (should_set) {
+        out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = "
+            << maybe_escape_identifier((*m_iter)->get_name()) << endl;
+      }
+    } else {
+      /** legacy Swift2/Cocoa */
+      if (all || (*m_iter)->get_req() == t_field::T_REQUIRED || (*m_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
+        out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = "
+            << maybe_escape_identifier((*m_iter)->get_name()) << endl;
+      }
     }
   }
 
@@ -548,34 +850,35 @@ void t_swift_generator::generate_swift_struct_hashable_extension(ofstream& out,
                                                                  t_struct* tstruct,
                                                                  bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
-
+  string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
   indent(out) << "extension " << tstruct->get_name() << " : Hashable";
-
   block_open(out);
-
   out << endl;
-
   indent(out) << visibility << " var hashValue : Int";
-
   block_open(out);
 
-
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
   if (!members.empty()) {
     indent(out) << "let prime = 31" << endl;
     indent(out) << "var result = 1" << endl;
-
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_field* tfield = *m_iter;
-      string accessor = field_is_optional(tfield) ? "?." : ".";
-      string defaultor = field_is_optional(tfield) ? " ?? 0" : "";
-      indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor
-                  <<  "hashValue" << defaultor << ")" << endl;
+    if (!tstruct->is_union()) {
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        t_field* tfield = *m_iter;
+        string accessor = field_is_optional(tfield) ? "?." : ".";
+        string defaultor = field_is_optional(tfield) ? " ?? 0" : "";
+        indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor
+                    <<  "hashValue" << defaultor << ")" << endl;
+      }
+    } else {
+      indent(out) << "switch self {" << endl;
+      for (m_iter = members.begin(); m_iter != members.end(); m_iter++) {
+        t_field *tfield = *m_iter;
+        indent(out) << "case ." << tfield->get_name() << "(let val): result = prime &* val.hashValue" << endl;
+      }
+      indent(out) << "}" << endl << endl;
     }
-
     indent(out) << "return result" << endl;
   }
   else {
@@ -583,11 +886,8 @@ void t_swift_generator::generate_swift_struct_hashable_extension(ofstream& out,
   }
 
   block_close(out);
-
   out << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -602,42 +902,51 @@ void t_swift_generator::generate_swift_struct_equatable_extension(ofstream& out,
                                                                   t_struct* tstruct,
                                                                   bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
-
-  indent(out) << visibility << " func ==(lhs: " << type_name(tstruct) << ", rhs: " << type_name(tstruct) << ") -> Bool";
+  string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
 
+  indent(out) << visibility << " func ==(lhs: " << type_name(tstruct) << ", rhs: "
+              << type_name(tstruct) << ") -> Bool";
   block_open(out);
-
   indent(out) << "return";
 
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
   if (members.size()) {
-
-    out << endl;
-
-    indent_up();
-
-    for (m_iter = members.begin(); m_iter != members.end();) {
-      t_field* tfield = *m_iter;
-      indent(out) << "(lhs." << maybe_escape_identifier(tfield->get_name())
-                  << " ?== rhs." << maybe_escape_identifier(tfield->get_name()) << ")";
-      if (++m_iter != members.end()) {
-        out << " &&";
-      }
+    if (!tstruct->is_union()) {
       out << endl;
+      indent_up();
+
+      for (m_iter = members.begin(); m_iter != members.end();) {
+        t_field* tfield = *m_iter;
+        indent(out) << "(lhs." << maybe_escape_identifier(tfield->get_name())
+                    << (gen_cocoa_ ? " ?" : " ") << "== rhs." << maybe_escape_identifier(tfield->get_name()) << ")"; // swift 2 ?== operator not in 3?
+        if (++m_iter != members.end()) {
+          out << " &&";
+        }
+        out << endl;
+      }
+      indent_down();
+    } else {
+      block_open(out);
+      indent(out) << "switch (lhs, rhs) {" << endl;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        t_field* tfield = *m_iter;
+        indent(out) << "case (." << tfield->get_name() << "(let lval), ."
+                    << tfield->get_name() << "(let rval)): return lval == rval"
+                    << endl;
+      }
+      indent(out) << "default: return false" << endl;
+      indent(out) << "}" << endl;
+      indent_down();
+      indent(out) << "}()" << endl;
     }
-
-    indent_down();
-
   }
   else {
     out << " true" << endl;
   }
 
   block_close(out);
-
   out << endl;
 }
 
@@ -658,7 +967,7 @@ void t_swift_generator::generate_swift_struct_implementation(ofstream& out,
 
   generate_swift_struct_equatable_extension(out, tstruct, is_private);
 
-  if (!is_private && !is_result) {
+  if (!is_private && !is_result && !gen_cocoa_) {  // old compiler didn't use debug_descriptions, OR it with gen_cocoa_ so the flag doesn't matter w/ cocoa
     generate_swift_struct_printable_extension(out, tstruct);
   }
 
@@ -687,123 +996,328 @@ void t_swift_generator::generate_swift_struct_thrift_extension(ofstream& out,
   block_open(out);
 
   out << endl;
+  if (!gen_cocoa_) {
+    /** Swift 3, no writer we just write field ID's */
+    string access = (is_private) ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
+    // generate fieldID's dictionary
+    out << indent() << access << " static var fieldIds: [String: Int32]";
+    block_open(out);
+    out << indent() << "return [";
+    const vector<t_field*>& fields = tstruct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    bool wrote = false;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      wrote = true;
+      out << "\"" << (*f_iter)->get_name() << "\": " << (*f_iter)->get_key() << ", ";
+    }
+    if (!wrote) {
+      // pad a colon
+      out << ":";
+    }
+    out << "]" << endl;
+    block_close(out);
+    out << endl;
+    out << indent() << access << " static var structName: String { return \""
+        << tstruct->get_name() << "\" }" << endl << endl;
 
-  generate_swift_struct_reader(out, tstruct, is_private);
+    if (tstruct->is_union()) {
+      generate_swift_union_reader(out, tstruct);
+    } else {
+      generate_swift_struct_reader(out, tstruct, is_private);
+    }
+  } else {
+    /** Legacy Swift2/Cocoa */
 
-  if (is_result) {
-    generate_swift_struct_result_writer(out, tstruct);
-  }
-  else {
-    generate_swift_struct_writer(out, tstruct, is_private);
+    generate_swift_struct_reader(out, tstruct, is_private);
+
+    if (is_result) {
+      generate_old_swift_struct_result_writer(out, tstruct);
+    }
+    else {
+      generate_old_swift_struct_writer(out, tstruct, is_private);
+    }
   }
 
   block_close(out);
-
   out << endl;
 }
 
-/**
- * Generates a function to read a struct from
- * from a protocol. (TStruct compliance)
- *
- * @param tstruct The structure definition
- * @param is_private
- *                Is the struct public or private
- */
-void t_swift_generator::generate_swift_struct_reader(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_private) {
-
-  string visibility = is_private ? "private" : "public";
-
-  indent(out) << visibility << " static func readValueFromProtocol(__proto: TProtocol) throws -> "
+void t_swift_generator::generate_swift_union_reader(ofstream& out, t_struct* tstruct) {
+  indent(out) << "public static func read(from proto: TProtocol) throws -> "
               << tstruct->get_name();
-
   block_open(out);
+  indent(out) << "_ = try proto.readStructBegin()" << endl;
 
+  indent(out) << "var ret: " << tstruct->get_name() << "?";
   out << endl;
-
-  indent(out) << "try __proto.readStructBegin()" << endl << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    bool optional = field_is_optional(*f_iter);
-    indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << " : "
-                << type_name((*f_iter)->get_type(), optional, !optional) << endl;
-  }
-
-  out << endl;
-
-  // Loop over reading in fields
   indent(out) << "fields: while true";
-
   block_open(out);
-
   out << endl;
-
-  indent(out) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl << endl;
+  indent(out) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl << endl;
   indent(out) << "switch (fieldID, fieldType)";
-
   block_open(out);
+  indent(out) << "case (_, .stop):            break fields" << endl;
 
-  indent(out) << "case (_, .STOP):" << endl;
-  indent_up();
-  indent(out) << "break fields" << endl << endl;
-  indent_down();
-
-  // Generate deserialization code for known cases
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):";// << endl;
+    string padding = "";
+
+    t_type* type = get_true_type((*f_iter)->get_type());
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+        case t_base_type::TYPE_STRING:
+        case t_base_type::TYPE_DOUBLE:
+          padding = "           ";
+          break;
+
+        case t_base_type::TYPE_BOOL:
+        case t_base_type::TYPE_I8:
+          padding = "            ";
+          break;
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+        case t_base_type::TYPE_I64:
+          padding = "             ";
+          break;
+        default: break;
+      }
+    } else if (type->is_enum() || type->is_set() || type->is_map()) {
+      padding = "             ";
+    } else if (type->is_struct() || type->is_xception()) {
+      padding = "           ";
+    } else if (type->is_list()) {
+      padding = "            ";
+    }
 
-    indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):" << endl;
-    indent_up();
-    indent(out) << maybe_escape_identifier((*f_iter)->get_name()) << " = try __proto.readValue() as "
-                << type_name((*f_iter)->get_type()) << endl << endl;
-    indent_down();
-
+    indent(out) << padding << "ret = " << tstruct->get_name() << "."
+                << (*f_iter)->get_name() << "(val: " << "try "
+                << type_name((*f_iter)->get_type(), false, false)
+                << ".read(from: proto))" << endl;
   }
 
-  indent(out) << "case let (_, unknownType):" << endl;
-  indent_up();
-  indent(out) << "try __proto.skipType(unknownType)" << endl;
-  indent_down();
+  indent(out) << "case let (_, unknownType):  try proto.skip(type: unknownType)" << endl;
 
   block_close(out);
+  indent(out) << "try proto.readFieldEnd()" << endl;
 
+  block_close(out);
   out << endl;
 
-  // Read field end marker
-  indent(out) << "try __proto.readFieldEnd()" << endl;
+  indent(out) << "try proto.readStructEnd()" << endl;
 
+  indent(out) << "if let ret = ret";
+  block_open(out);
+  indent(out) << "return ret" << endl;
   block_close(out);
-
   out << endl;
-
-  indent(out) << "try __proto.readStructEnd()" << endl;
-
+  indent(out) << "throw TProtocolError(error: .unknown, message: \"Missing required value for type: "
+              << tstruct->get_name() << "\")";
+  block_close(out);
   out << endl;
 
-  if (struct_has_required_fields(tstruct)) {
-    // performs various checks (e.g. check that all required fields are set)
-    indent(out) << "// Required fields" << endl;
+}
 
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      if (field_is_optional(*f_iter)) {
-        continue;
+/**
+ * Generates a function to read a struct from
+ * from a protocol. (TStruct compliance)
+ *
+ * @param tstruct The structure definition
+ * @param is_private
+ *                Is the struct public or private
+ */
+void t_swift_generator::generate_swift_struct_reader(ofstream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_private) {
+
+  if (!gen_cocoa_) {
+    /** Swift 3 case */
+    string visibility = is_private ? "fileprivate" : "public";
+
+    indent(out) << visibility << " static func read(from proto: TProtocol) throws -> "
+               << tstruct->get_name();
+
+    block_open(out);
+    indent(out) << "_ = try proto.readStructBegin()" << endl;
+
+    const vector<t_field*>& fields = tstruct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      bool optional = field_is_optional(*f_iter);
+      indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << ": "
+                  << type_name((*f_iter)->get_type(), optional, !optional) << endl;
+    }
+
+    out << endl;
+
+    // Loop over reading in fields
+    indent(out) << "fields: while true";
+    block_open(out);
+    out << endl;
+
+    indent(out) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl << endl;
+    indent(out) << "switch (fieldID, fieldType)";
+    block_open(out);
+    indent(out) << "case (_, .stop):            break fields" << endl;
+
+
+    // Generate deserialization code for known cases
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):";// << endl;
+      string padding = "";
+
+      t_type* type = get_true_type((*f_iter)->get_type());
+      if (type->is_base_type()) {
+        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+        switch (tbase) {
+          case t_base_type::TYPE_STRING:
+          case t_base_type::TYPE_DOUBLE:
+            padding = "           ";
+          break;
+
+          case t_base_type::TYPE_BOOL:
+          case t_base_type::TYPE_I8:
+            padding = "            ";
+          break;
+          case t_base_type::TYPE_I16:
+          case t_base_type::TYPE_I32:
+          case t_base_type::TYPE_I64:
+            padding = "             ";
+          break;
+          default: break;
+        }
+      } else if (type->is_enum() || type->is_set() || type->is_map()) {
+        padding = "             ";
+      } else if (type->is_struct() || type->is_xception()) {
+        padding = "           ";
+      } else if (type->is_list()) {
+        padding = "            ";
       }
-      indent(out) << "try __proto.validateValue(" << (*f_iter)->get_name() << ", "
-                  << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
+
+      out << padding << maybe_escape_identifier((*f_iter)->get_name()) << " = try "
+          << type_name((*f_iter)->get_type(), false, false) << ".read(from: proto)" << endl;
     }
-  }
 
-  out << endl;
+    indent(out) << "case let (_, unknownType):  try proto.skip(type: unknownType)" << endl;
+    block_close(out);
+    out << endl;
 
-  indent(out) << "return " << tstruct->get_name() << "(";
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name());
-    if (++f_iter != fields.end()) {
-      out << ", ";
+    // Read field end marker
+    indent(out) << "try proto.readFieldEnd()" << endl;
+    block_close(out);
+    out << endl;
+    indent(out) << "try proto.readStructEnd()" << endl;
+
+    if (struct_has_required_fields(tstruct)) {
+      // performs various checks (e.g. check that all required fields are set)
+      indent(out) << "// Required fields" << endl;
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if (field_is_optional(*f_iter)) {
+          continue;
+        }
+        indent(out) << "try proto.validateValue(" << (*f_iter)->get_name() << ", "
+                    << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
+      }
+    }
+
+    out << endl;
+
+    indent(out) << "return " << tstruct->get_name() << "(";
+    for (f_iter = fields.begin(); f_iter != fields.end();) {
+      out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name());
+      if (++f_iter != fields.end()) {
+        out << ", ";
+      }
+    }
+
+  } else {
+    /** Legacy Swif2/Cocoa case */
+    string visibility = is_private ? "private" : "public";
+
+    indent(out) << visibility << " static func readValueFromProtocol(__proto: TProtocol) throws -> "
+                << tstruct->get_name();
+
+    block_open(out);
+    out << endl;
+    indent(out) << "try __proto.readStructBegin()" << endl << endl;
+
+    const vector<t_field*>& fields = tstruct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      bool optional = field_is_optional(*f_iter);
+      indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << " : "
+                  << type_name((*f_iter)->get_type(), optional, !optional) << endl;
+    }
+
+    out << endl;
+
+    // Loop over reading in fields
+    indent(out) << "fields: while true";
+    block_open(out);
+    out << endl;
+
+    indent(out) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl << endl;
+    indent(out) << "switch (fieldID, fieldType)";
+
+    block_open(out);
+
+    indent(out) << "case (_, .STOP):" << endl;
+    indent_up();
+    indent(out) << "break fields" << endl << endl;
+    indent_down();
+
+    // Generate deserialization code for known cases
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+
+      indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):" << endl;
+      indent_up();
+      indent(out) << maybe_escape_identifier((*f_iter)->get_name()) << " = try __proto.readValue() as "
+                  << type_name((*f_iter)->get_type()) << endl << endl;
+      indent_down();
+
+    }
+
+    indent(out) << "case let (_, unknownType):" << endl;
+    indent_up();
+    indent(out) << "try __proto.skipType(unknownType)" << endl;
+    indent_down();
+    block_close(out);
+    out << endl;
+
+    // Read field end marker
+    indent(out) << "try __proto.readFieldEnd()" << endl;
+
+    block_close(out);
+    out << endl;
+    indent(out) << "try __proto.readStructEnd()" << endl;
+    out << endl;
+
+    if (struct_has_required_fields(tstruct)) {
+      // performs various checks (e.g. check that all required fields are set)
+      indent(out) << "// Required fields" << endl;
+
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        if (field_is_optional(*f_iter)) {
+          continue;
+        }
+        indent(out) << "try __proto.validateValue(" << (*f_iter)->get_name() << ", "
+                    << "named: \"" << (*f_iter)->get_name() << "\")" << endl;
+      }
+    }
+
+    out << endl;
+
+    indent(out) << "return " << tstruct->get_name() << "(";
+    for (f_iter = fields.begin(); f_iter != fields.end();) {
+      out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name());
+      if (++f_iter != fields.end()) {
+        out << ", ";
+      }
     }
   }
   out << ")" << endl;
@@ -815,22 +1329,21 @@ void t_swift_generator::generate_swift_struct_reader(ofstream& out,
 
 /**
  * Generates a function to write a struct to
- * a protocol. (TStruct compliance)
+ * a protocol. (TStruct compliance) ONLY FOR SWIFT2/COCOA
  *
  * @param tstruct The structure definition
  * @param is_private
  *                Is the struct public or private
  */
-void t_swift_generator::generate_swift_struct_writer(ofstream& out,
-                                                     t_struct* tstruct,
-                                                     bool is_private) {
+void t_swift_generator::generate_old_swift_struct_writer(ofstream& out,
+                                                         t_struct* tstruct,
+                                                         bool is_private) {
 
   string visibility = is_private ? "private" : "public";
 
-  indent(out) << visibility << " static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";
-
+  indent(out) << visibility << " static func writeValue(__value: " << tstruct->get_name()
+              << ", toProtocol __proto: TProtocol) throws";
   block_open(out);
-
   out << endl;
 
   string name = tstruct->get_name();
@@ -838,7 +1351,6 @@ void t_swift_generator::generate_swift_struct_writer(ofstream& out,
   vector<t_field*>::const_iterator f_iter;
 
   indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl;
-
   out << endl;
 
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -865,37 +1377,30 @@ void t_swift_generator::generate_swift_struct_writer(ofstream& out,
   }
 
   indent(out) << "try __proto.writeFieldStop()" << endl << endl;
-
   indent(out) << "try __proto.writeStructEnd()" << endl;
-
   block_close(out);
-
   out << endl;
 }
 
 /**
  * Generates a function to read a struct from
- * from a protocol. (TStruct compliance)
+ * from a protocol. (TStruct compliance)  ONLY FOR SWIFT 2/COCOA
  *
  * This is specifically a function result. Only
  * the first available field is written.
  *
  * @param tstruct The structure definition
  */
-void t_swift_generator::generate_swift_struct_result_writer(ofstream& out, t_struct* tstruct) {
-
-  indent(out) << "private static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";
+void t_swift_generator::generate_old_swift_struct_result_writer(ofstream& out, t_struct* tstruct) {
 
+  indent(out) << "private static func writeValue(__value: " << tstruct->get_name()
+              << ", toProtocol __proto: TProtocol) throws";
   block_open(out);
-
   out << endl;
-
   string name = tstruct->get_name();
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
-
   indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl;
-
   out << endl;
 
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
@@ -914,11 +1419,8 @@ void t_swift_generator::generate_swift_struct_result_writer(ofstream& out, t_str
   }
   // Write the struct map
   indent(out) << "try __proto.writeFieldStop()" << endl << endl;
-
   indent(out) << "try __proto.writeStructEnd()" << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -931,39 +1433,56 @@ void t_swift_generator::generate_swift_struct_printable_extension(ofstream& out,
 
   // Allow use of debugDescription so the app can add description via a cateogory/extension
 
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
   indent(out) << "extension " << tstruct->get_name() << " : "
               << (debug_descriptions_ ? "CustomDebugStringConvertible" : "CustomStringConvertible");
 
   block_open(out);
-
   out << endl;
-
   indent(out) << "public var description : String";
-
   block_open(out);
+  indent(out) << "var desc = \"" << tstruct->get_name();
 
-  indent(out) << "var desc = \"" << tstruct->get_name() << "(\"" << endl;
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    indent(out) << "desc += \"" << (*f_iter)->get_name()
-                << "=\\(self." << maybe_escape_identifier((*f_iter)->get_name()) << ")";
-    if (++f_iter != fields.end()) {
-      out << ", ";
+  if (!gen_cocoa_) {
+    if (!tstruct->is_union()) {
+      out << "(\"" << endl;
+      for (f_iter = fields.begin(); f_iter != fields.end();) {
+        indent(out) << "desc += \"" << (*f_iter)->get_name()
+                    << "=\\(String(describing: self." << maybe_escape_identifier((*f_iter)->get_name()) << "))";
+        if (++f_iter != fields.end()) {
+          out << ", ";
+        }
+        out << "\"" << endl;
+      }
+    } else {
+      out << ".\"" << endl;
+      indent(out) << "switch self {" << endl;
+      for (f_iter = fields.begin(); f_iter != fields.end();f_iter++) {
+        indent(out) << "case ." << (*f_iter)->get_name() << "(let val): "
+                    << "desc += \"" << (*f_iter)->get_name() << "(val: \\(val))\""
+                    << endl;
+      }
+      indent(out) << "}" << endl;
     }
-    out << "\"" << endl;
+  } else {
+    out << "(\"" << endl;
+    for (f_iter = fields.begin(); f_iter != fields.end();) {
+      indent(out) << "desc += \"" << (*f_iter)->get_name()
+                  << "=\\(self." << maybe_escape_identifier((*f_iter)->get_name()) << ")";
+      if (++f_iter != fields.end()) {
+        out << ", ";
+      }
+      out << "\"" << endl;
+    }
+    indent(out) << "desc += \")\"" << endl;
   }
-  indent(out) << "desc += \")\"" << endl;
-  indent(out) << "return desc" << endl;
 
+  indent(out) << "return desc" << endl;
   block_close(out);
-
   out << endl;
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1077,28 +1596,46 @@ void t_swift_generator::generate_function_helpers(t_service *tservice, t_functio
  * @param tservice The service to generate a protocol definition for
  */
 void t_swift_generator::generate_swift_service_protocol(ofstream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    string doc = tservice->get_doc();
+    generate_docstring(out, doc);
+
+    indent(out) << "public protocol " << tservice->get_name();
+    t_service* parent = tservice->get_extends();
+    if (parent != NULL) {
+      out << " : " << parent->get_name();
+    }
+    block_open(out);
+    out << endl;
 
-  indent(out) << "public protocol " << tservice->get_name();
+    vector<t_function*> functions = tservice->get_functions();
+    vector<t_function*>::iterator f_iter;
 
-  block_open(out);
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      function_docstring(out, *f_iter);
+      indent(out) << function_signature(*f_iter) << endl << endl;
+    }
 
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter;
+  } else {
+    indent(out) << "public protocol " << tservice->get_name();
+    block_open(out);
 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << endl;
-    indent(out) << function_signature(*f_iter) << "  // exceptions: ";
-    t_struct* xs = (*f_iter)->get_xceptions();
-    const vector<t_field*>& xceptions = xs->get_members();
-    vector<t_field*>::const_iterator x_iter;
-    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-      out << type_name((*x_iter)->get_type()) + ", ";
+    vector<t_function*> functions = tservice->get_functions();
+    vector<t_function*>::iterator f_iter;
+
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      out << endl;
+      indent(out) << function_signature(*f_iter) << "  // exceptions: ";
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        out << type_name((*x_iter)->get_type()) + ", ";
+      }
+      out << endl;
     }
-    out << endl;
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1108,25 +1645,34 @@ void t_swift_generator::generate_swift_service_protocol(ofstream& out, t_service
  * @param tservice The service to generate a protocol definition for
  */
 void t_swift_generator::generate_swift_service_protocol_async(ofstream& out, t_service* tservice) {
-
+  if (!gen_cocoa_) {
+    string doc = tservice->get_doc();
+    generate_docstring(out, doc);
+  }
   indent(out) << "public protocol " << tservice->get_name() << "Async";
 
   block_open(out);
+  if (!gen_cocoa_) {  out << endl; }
 
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter;
 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    out << endl;
-    indent(out) << async_function_signature(*f_iter) << endl;
-    if (promise_kit_) {
-      indent(out) << promise_function_signature(*f_iter) << endl;
+  if (!gen_cocoa_) {
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      async_function_docstring(out, *f_iter);
+      indent(out) << async_function_signature(*f_iter) << endl << endl;
+    }
+  } else {
+    for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+      out << endl;
+      indent(out) << async_function_signature(*f_iter) << endl;
+      if (promise_kit_) {
+        indent(out) << promise_function_signature(*f_iter) << endl;
+      } //
+      out << endl;
     }
-    out << endl;
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1135,45 +1681,41 @@ void t_swift_generator::generate_swift_service_protocol_async(ofstream& out, t_s
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_swift_generator::generate_swift_service_client(ofstream& out,
-                                                                t_service* tservice) {
-
-  indent(out) << "public class " << tservice->get_name() << "Client /* : " << tservice->get_name() << " */";
-
-  block_open(out);
-
-  out << endl;
-
-  indent(out) << "let __inProtocol : TProtocol" << endl << endl;
-
-  indent(out) << "let __outProtocol : TProtocol" << endl << endl;
-
-  indent(out) << "public init(inoutProtocol: TProtocol)";
-
-  block_open(out);
-
-  indent(out) << "__inProtocol = inoutProtocol" << endl;
-
-  indent(out) << "__outProtocol = inoutProtocol" << endl;
-
-  block_close(out);
-
-  out << endl;
-
-  indent(out) << "public init(inProtocol: TProtocol, outProtocol: TProtocol)";
-
-  block_open(out);
-
-  indent(out) << "__inProtocol = inProtocol" << endl;
+void t_swift_generator::generate_swift_service_client(ofstream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    indent(out) << "open class " << tservice->get_name() << "Client";// : "
+
+    // Inherit from ParentClient
+    t_service* parent = tservice->get_extends();
+    out << " : " << ((parent == NULL) ? "TClient" : parent->get_name() + "Client");
+    out <<  " /* , " << tservice->get_name() << " */";
+    block_open(out);
+    out << endl;
+  } else {
+    // a
+    indent(out) << "public class " << tservice->get_name() << "Client /* : " << tservice->get_name() << " */";
+    block_open(out);
+    out << endl;
 
-  indent(out) << "__outProtocol = outProtocol" << endl;
+    indent(out) << "let __inProtocol : TProtocol" << endl << endl;
+    indent(out) << "let __outProtocol : TProtocol" << endl << endl;
+    indent(out) << "public init(inoutProtocol: TProtocol)";
+    block_open(out);
 
-  block_close(out);
+    indent(out) << "__inProtocol = inoutProtocol" << endl;
+    indent(out) << "__outProtocol = inoutProtocol" << endl;
+    block_close(out);
+    out << endl;
 
-  out << endl;
+    indent(out) << "public init(inProtocol: TProtocol, outProtocol: TProtocol)";
+    block_open(out);
+    indent(out) << "__inProtocol = inProtocol" << endl;
+    indent(out) << "__outProtocol = outProtocol" << endl;
+    block_close(out);
+    out << endl;
+  }
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1182,33 +1724,35 @@ void t_swift_generator::generate_swift_service_client(ofstream& out,
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_swift_generator::generate_swift_service_client_async(ofstream& out,
-                                                                      t_service* tservice) {
-
-  indent(out) << "public class " << tservice->get_name() << "AsyncClient /* : " << tservice->get_name() << " */";
-
-  block_open(out);
-
-  out << endl;
-
-  indent(out) << "let __protocolFactory : TProtocolFactory" << endl << endl;
-
-  indent(out) << "let __transportFactory : TAsyncTransportFactory" << endl << endl;
-
-  indent(out) << "public init(protocolFactory: TProtocolFactory, transportFactory: TAsyncTransportFactory)";
+void t_swift_generator::generate_swift_service_client_async(ofstream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    indent(out) << "open class " << tservice->get_name()
+                << "AsyncClient<Protocol: TProtocol, Factory: TAsyncTransportFactory>";// : "
 
-  block_open(out);
-
-  indent(out) << "__protocolFactory = protocolFactory" << endl;
+    // Inherit from ParentClient
+    t_service* parent = tservice->get_extends();
 
-  indent(out) << "__transportFactory = transportFactory" << endl;
+    out << " : " << ((parent == NULL) ? "T" :  parent->get_name()) + "AsyncClient<Protocol, Factory>";
+    out <<  " /* , " << tservice->get_name() << " */";
 
-  block_close(out);
+    block_open(out);
+    out << endl;
+  } else {
+    indent(out) << "public class " << tservice->get_name() << "AsyncClient /* : " << tservice->get_name() << " */";
+    block_open(out);
+    out << endl;
 
-  out << endl;
+    indent(out) << "let __protocolFactory : TProtocolFactory" << endl << endl;
+    indent(out) << "let __transportFactory : TAsyncTransportFactory" << endl << endl;
+    indent(out) << "public init(protocolFactory: TProtocolFactory, transportFactory: TAsyncTransportFactory)";
+    block_open(out);
 
+    indent(out) << "__protocolFactory = protocolFactory" << endl;
+    indent(out) << "__transportFactory = transportFactory" << endl;
+    block_close(out);
+    out << endl;
+  }
   block_close(out);
-
   out << endl;
 }
 
@@ -1218,29 +1762,38 @@ void t_swift_generator::generate_swift_service_client_async(ofstream& out,
  *
  * @param tservice The service to generate a client interface definition for
  */
-void t_swift_generator::generate_swift_service_server(ofstream& out,
-                                                                t_service* tservice) {
-
-  indent(out) << "public class " << tservice->get_name() << "Processor : NSObject /* " << tservice->get_name() << " */";
+void t_swift_generator::generate_swift_service_server(ofstream& out, t_service* tservice) {
+  if (!gen_cocoa_) {
+    indent(out) << "open class " << tservice->get_name() << "Processor /* " << tservice->get_name() << " */";
 
-  block_open(out);
+    block_open(out);
+    out << endl;
+    out << indent() << "typealias ProcessorHandlerDictionary = "
+        << "[String: (Int32, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl
+        << endl
+        << indent() << "public var service: " << tservice->get_name() << endl
+        << endl
+        << indent() << "public required init(service: " << tservice->get_name() << ")";
+  } else {
+    indent(out) << "public class " << tservice->get_name() << "Processor : NSObject /* "
+                << tservice->get_name() << " */";
+    block_open(out);
+    out << endl;
 
-  out << endl;
+    out << indent() << "typealias ProcessorHandlerDictionary = "
+        << "[String: (Int, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl
+        << endl
+        << indent() << "let service : " << tservice->get_name() << endl
+        << endl
+        << indent() << "public init(service: " << tservice->get_name() << ")";
+  }
 
-  out << indent() << "typealias ProcessorHandlerDictionary = "
-                  << "[String: (Int, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl
-      << endl
-      << indent() << "let service : " << tservice->get_name() << endl
-      << endl
-      << indent() << "public init(service: " << tservice->get_name() << ")";
   block_open(out);
   indent(out) << "self.service = service" << endl;
   block_close(out);
-
   out << endl;
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1268,40 +1821,65 @@ void t_swift_generator::generate_swift_service_client_send_function_implementati
   string argsname = function_args_helper_struct_type(tservice, tfunction);
   t_struct* arg_struct = tfunction->get_arglist();
 
+  string proto = needs_protocol ? (gen_cocoa_ ? "__outProtocol" : "on outProtocol") : "";
   // Open function
-  indent(out) << "private func " << send_function.get_name() << "(" << argument_list(tfunction->get_arglist(), needs_protocol ? "__outProtocol" : "", true) << ") throws";
+  indent(out) << "private func " << send_function.get_name() << "("
+              << argument_list(tfunction->get_arglist(), proto, true)
+              << ") throws";
   block_open(out);
+  if (!gen_cocoa_) {
+    // Serialize the request
+    indent(out) << "try outProtocol.writeMessageBegin(name: \"" << funname << "\", "
+                << "type: " << (tfunction->is_oneway() ? ".oneway" : ".call") << ", "
+                << "sequenceID: 0)" << endl;
 
-  out << endl;
+    indent(out) << "let args = " << argsname << "(";
 
-  // Serialize the request
-  indent(out) << "try __outProtocol.writeMessageBeginWithName(\"" << funname << "\", "
-              << "type: " << (tfunction->is_oneway() ? ".ONEWAY" : ".CALL") << ", "
-              << "sequenceID: 0)" << endl;
+    // write out function parameters
 
-  out << endl;
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end();) {
+      t_field *tfield = (*f_iter);
+      out << tfield->get_name() << ": " << tfield->get_name();
+      if (++f_iter != fields.end()) {
+        out << ", ";
+      }
+    }
+    out << ")" << endl;
+    indent(out) << "try args.write(to: outProtocol)" << endl;
+    indent(out) << "try outProtocol.writeMessageEnd()" << endl;
+  } else {
+    out << endl;
 
-  indent(out) << "let __args = " << argsname << "(";
+    // Serialize the request
+    indent(out) << "try __outProtocol.writeMessageBeginWithName(\"" << funname << "\", "
+                << "type: " << (tfunction->is_oneway() ? ".ONEWAY" : ".CALL") << ", "
+                << "sequenceID: 0)" << endl;
 
-  // write out function parameters
+    out << endl;
 
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
+    indent(out) << "let __args = " << argsname << "(";
 
-  for (f_iter = fields.begin(); f_iter != fields.end();) {
-    t_field *tfield = (*f_iter);
-    out << tfield->get_name() << ": " << tfield->get_name();
-    if (++f_iter != fields.end()) {
-      out << ", ";
+    // write out function parameters
+
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator f_iter;
+
+    for (f_iter = fields.begin(); f_iter != fields.end();) {
+      t_field *tfield = (*f_iter);
+      out << tfield->get_name() << ": " << tfield->get_name();
+      if (++f_iter != fields.end()) {
+        out << ", ";
+      }
     }
+    out << ")" << endl;
+    indent(out) << "try " << argsname << ".writeValue(__args, toProtocol: __outProtocol)" << endl << endl;
+    indent(out) << "try __outProtocol.writeMessageEnd()" << endl;
   }
-  out << ")" << endl;
-  indent(out) << "try " << argsname << ".writeValue(__args, toProtocol: __outProtocol)" << endl << endl;
-
-  indent(out) << "try __outProtocol.writeMessageEnd()" << endl;
 
   block_close(out);
-
   out << endl;
 }
 
@@ -1322,66 +1900,115 @@ void t_swift_generator::generate_swift_service_client_recv_function_implementati
 
   // Open function
   indent(out) << "private func recv_" << tfunction->get_name() << "(";
+  if (!gen_cocoa_) {
+    if (needs_protocol) {
+      out << "on inProtocol: TProtocol";
+    }
+    out << ") throws";
+    if (!tfunction->get_returntype()->is_void()) {
+      out << " -> " << type_name(tfunction->get_returntype());
+    }
 
-  if (needs_protocol) {
-    out << "__inProtocol: TProtocol";
-  }
+    block_open(out);
 
-  out << ") throws";
+    // check for an exception
 
-  if (!tfunction->get_returntype()->is_void()) {
-    out << " -> " << type_name(tfunction->get_returntype());
-  }
+    indent(out) << "try inProtocol.readResultMessageBegin() " << endl;
+
+    string resultname = function_result_helper_struct_type(tservice, tfunction);
+    indent(out);
+    if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) {
+      out << "let result = ";
+    } else {
+      out << "_ = ";
+    }
+
+    string return_type_name = type_name(tfunction->get_returntype());
+    out << "try " << resultname << ".read(from: inProtocol)" << endl;
+
+    indent(out) << "try inProtocol.readMessageEnd()" << endl << endl;
+
+    // Careful, only return _result if not a void function
+    if (!tfunction->get_returntype()->is_void()) {
+      indent(out) << "if let success = result.success";
+      block_open(out);
+      indent(out) << "return success" << endl;
+      block_close(out);
+    }
+
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
 
-  block_open(out);
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      indent(out) << "if let " << (*x_iter)->get_name() << " = result." << (*x_iter)->get_name();
+      block_open(out);
+      indent(out) << "throw " << (*x_iter)->get_name() << endl;
+      block_close(out);
+    }
 
-  // check for an exception
+    // If you get here it's an exception, unless a void function
+    if (!tfunction->get_returntype()->is_void()) {
+      indent(out) << "throw TApplicationError(error: .missingResult(methodName: \""
+                  << tfunction->get_name() << "\"))" << endl;
+    }
+  } else {
+    if (needs_protocol) {
+      out << "__inProtocol: TProtocol";
+    }
 
-  out << endl;
+    out << ") throws";
 
-  indent(out) << "try __inProtocol.readResultMessageBegin() " << endl << endl;
+    if (!tfunction->get_returntype()->is_void()) {
+      out << " -> " << type_name(tfunction->get_returntype());
+    }
 
-  string resultname = function_result_helper_struct_type(tservice, tfunction);
-  indent(out);
-  if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) {
-    out << "let __result = ";
-  }
-  out << "try " << resultname << ".readValueFromProtocol(__inProtocol)" << endl << endl;
+    block_open(out);
 
-  indent(out) << "try __inProtocol.readMessageEnd()" << endl << endl;
+    // check for an exception
+    out << endl;
+    indent(out) << "try __inProtocol.readResultMessageBegin() " << endl << endl;
+    string resultname = function_result_helper_struct_type(tservice, tfunction);
+    indent(out);
+    if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) {
+      out << "let __result = ";
+    }
+    out << "try " << resultname << ".readValueFromProtocol(__inProtocol)" << endl << endl;
 
-  // Careful, only return _result if not a void function
-  if (!tfunction->get_returntype()->is_void()) {
-    indent(out) << "if let __success = __result.success";
-    block_open(out);
-    indent(out) << "return __success" << endl;
-    block_close(out);
-  }
+    indent(out) << "try __inProtocol.readMessageEnd()" << endl << endl;
 
-  t_struct* xs = tfunction->get_xceptions();
-  const vector<t_field*>& xceptions = xs->get_members();
-  vector<t_field*>::const_iterator x_iter;
+    // Careful, only return _result if not a void function
+    if (!tfunction->get_returntype()->is_void()) {
+      indent(out) << "if let __success = __result.success";
+      block_open(out);
+      indent(out) << "return __success" << endl;
+      block_close(out);
+    }
 
-  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
-    indent(out) << "if let " << (*x_iter)->get_name() << " = __result." << (*x_iter)->get_name();
-    block_open(out);
-    indent(out) << "throw " << (*x_iter)->get_name() << endl;
-    block_close(out);
-  }
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
 
-  // If you get here it's an exception, unless a void function
-  if (!tfunction->get_returntype()->is_void()) {
-    indent(out) << "throw NSError(" << endl;
-    indent_up();
-    indent(out) << "domain: TApplicationErrorDomain, " << endl;
-    indent(out) << "code: Int(TApplicationError.MissingResult.rawValue)," << endl;
-    indent(out) << "userInfo: [TApplicationErrorMethodKey: \"" << tfunction->get_name() << "\"])" << endl;
-    indent_down();
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      indent(out) << "if let " << (*x_iter)->get_name() << " = __result." << (*x_iter)->get_name();
+      block_open(out);
+      indent(out) << "throw " << (*x_iter)->get_name() << endl;
+      block_close(out);
+    }
+
+    // If you get here it's an exception, unless a void function
+    if (!tfunction->get_returntype()->is_void()) {
+      indent(out) << "throw NSError(" << endl;
+      indent_up();
+      indent(out) << "domain: TApplicationErrorDomain, " << endl;
+      indent(out) << "code: Int(TApplicationError.MissingResult.rawValue)," << endl;
+      indent(out) << "userInfo: [TApplicationErrorMethodKey: \"" << tfunction->get_name() << "\"])" << endl;
+      indent_down();
+    }
   }
 
   // Close function
   block_close(out);
-
   out << endl;
 }
 
@@ -1424,7 +2051,11 @@ void t_swift_generator::generate_swift_service_client_send_async_function_invoca
   const vector<t_field*>& fields = arg_struct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
-  indent(out) << "try send_" << tfunction->get_name() << "(__protocol";
+  if (!gen_cocoa_) {
+    indent(out) << "try send_" << tfunction->get_name() << "(on: proto";
+  } else {
+    indent(out) << "try send_" << tfunction->get_name() << "(__protocol"; //
+  }
 
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     out << ", " << (*f_iter)->get_name() << ": " << (*f_iter)->get_name();
@@ -1442,11 +2073,8 @@ void t_swift_generator::generate_swift_service_client_implementation(ofstream& o
                                                                      t_service* tservice) {
 
   string name = tservice->get_name() + "Client";
-
   indent(out) << "extension " << name << " : " << tservice->get_name();
-
   block_open(out);
-
   out << endl;
 
   // generate client method implementations
@@ -1462,16 +2090,17 @@ void t_swift_generator::generate_swift_service_client_implementation(ofstream& o
 
     // Open function
     indent(out) << "public " << function_signature(*f_iter);
-
     block_open(out);
 
-    out << endl;
+    if (gen_cocoa_) { out << endl; }
 
     generate_swift_service_client_send_function_invocation(out, *f_iter);
-
-    out << endl;
-
-    indent(out) << "try __outProtocol.transport().flush()" << endl << endl;
+    if (!gen_cocoa_) {
+      indent(out) << "try outProtocol.transport.flush()" << endl;
+    } else {
+      out << endl;
+      indent(out) << "try __outProtocol.transport().flush()" << endl << endl;
+    }
 
     if (!(*f_iter)->is_oneway()) {
       if ((*f_iter)->get_returntype()->is_void()) {
@@ -1480,14 +2109,10 @@ void t_swift_generator::generate_swift_service_client_implementation(ofstream& o
         indent(out) << "return try recv_" << (*f_iter)->get_name() << "()" << endl;
       }
     }
-
     block_close(out);
-
     out << endl;
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1496,16 +2121,16 @@ void t_swift_generator::generate_swift_service_client_implementation(ofstream& o
  *
  * @param tservice The service to generate an implementation for
  */
-void t_swift_generator::generate_swift_service_client_async_implementation(ofstream& out,
-                                                                           t_service* tservice) {
-
+void t_swift_generator::generate_swift_service_client_async_implementation(ofstream& out, t_service* tservice) {
+  if (gen_cocoa_) {
+    generate_old_swift_service_client_async_implementation(out, tservice);
+    return;
+  }
   string name = tservice->get_name() + "AsyncClient";
   string protocol_name = tservice->get_name() + "Async";
 
   indent(out) << "extension " << name << " : " << protocol_name;
-
   block_open(out);
-
   out << endl;
 
   // generate client method implementations
@@ -1521,7 +2146,86 @@ void t_swift_generator::generate_swift_service_client_async_implementation(ofstr
 
     indent(out) << "public " << async_function_signature(*f_iter);
     block_open(out);
+    out << endl;
+    out << indent() << "let transport   = factory.newTransport()" << endl
+        << indent() << "let proto = Protocol(on: transport)" << endl
+        << endl;
+
+    out << indent() << "do";
+    block_open(out);
+
+    generate_swift_service_client_send_async_function_invocation(out, *f_iter);
+
+    indent_down();
+    out << indent() << "} catch let error {" << endl;
+    indent_up();
+    out << indent() << "completion(.error(error))" << endl;
+    block_close(out);
+
+    out << endl;
+
+    bool ret_is_void = (*f_iter)->get_returntype()->is_void();
+    bool is_oneway = (*f_iter)->is_oneway();
+
+    string error_completion_call = "completion(.error(error))";
+    indent(out) << "transport.flush";
+    block_open(out);
+    out << indent() << "(trans, error) in" << endl << endl;
+    out << indent() << "if let error = error";
+    block_open(out);
+    out << indent() << error_completion_call << endl;
+    block_close(out);
+
+    if (!is_oneway) {
+      out << indent() << "do";
+      block_open(out);
+      indent(out);
+      if (!ret_is_void) {
+        out << "let result = ";
+      }
+      out << "try self.recv_" << (*f_iter)->get_name() << "(on: proto)" << endl;
+
+      out << indent() << (ret_is_void ? "completion(.success(Void()))" : "completion(.success(result))") << endl;
+      indent_down();
+      out << indent() << "} catch let error {" << endl;
+      indent_up();
+      out << indent() << error_completion_call << endl;
+
+      block_close(out);
+    } else {
+      out << indent() << "completion(.success(Void()))" << endl;
+    }
+    block_close(out);
+    block_close(out);
+
+  }
+  block_close(out);
+  out << endl;
+}
+
+void t_swift_generator::generate_old_swift_service_client_async_implementation(ofstream& out,
+                                                                               t_service* tservice) {
+
+  string name = tservice->get_name() + "AsyncClient";
+  string protocol_name = tservice->get_name() + "Async";
+
+  indent(out) << "extension " << name << " : " << protocol_name;
+  block_open(out);
+  out << endl;
+
+  // generate client method implementations
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::const_iterator f_iter;
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+
+    generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, true);
+
+    if (!(*f_iter)->is_oneway()) {
+      generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, true);
+    }
 
+    indent(out) << "public " << async_function_signature(*f_iter);
+    block_open(out);
     out << endl;
 
     out << indent() << "let __transport = __transportFactory.newTransport()" << endl
@@ -1529,7 +2233,6 @@ void t_swift_generator::generate_swift_service_client_async_implementation(ofstr
         << endl;
 
     generate_swift_service_client_send_async_function_invocation(out, *f_iter);
-
     out << endl;
 
     indent(out) << "__transport.flushWithCompletion(";
@@ -1563,9 +2266,7 @@ void t_swift_generator::generate_swift_service_client_async_implementation(ofstr
       indent(out) << ", failure: failure)" << endl;
     }
 
-
     block_close(out);
-
     out << endl;
 
     // Promise function
@@ -1580,9 +2281,7 @@ void t_swift_generator::generate_swift_service_client_async_implementation(ofstr
           << endl;
 
       generate_swift_service_client_send_async_function_invocation(out, *f_iter);
-
       out << endl;
-
       indent(out) << "__transport.flushWithCompletion(";
 
       if ((*f_iter)->is_oneway()) {
@@ -1620,17 +2319,13 @@ void t_swift_generator::generate_swift_service_client_async_implementation(ofstr
       }
 
       indent(out) << "return __promise" << endl;
-
       block_close(out);
-
       out << endl;
 
     }
 
   }
-
   block_close(out);
-
   out << endl;
 }
 
@@ -1650,14 +2345,11 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
 
   indent(out) << "extension " << name << " : TProcessor";
   block_open(out);
-
   out << endl;
-
-  indent(out) << "static let processorHandlers : ProcessorHandlerDictionary =";
+  indent(out) << "static let processorHandlers" << (gen_cocoa_ ? " " : "") << ": ProcessorHandlerDictionary =";
   block_open(out);
 
   out << endl;
-
   out << indent() << "var processorHandlers = ProcessorHandlerDictionary()" << endl << endl;
 
   // generate method map for routing incoming calls
@@ -1673,10 +2365,17 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
         << endl;
 
     indent_up();
-    out << indent() << "let args = try " << args_type << ".readValueFromProtocol(inProtocol)" << endl
-        << endl
-        << indent() << "try inProtocol.readMessageEnd()" << endl
-        << endl;
+    if (!gen_cocoa_) {
+      out << indent() << "let args = try " << args_type << ".read(from: inProtocol)" << endl
+          << endl
+          << indent() << "try inProtocol.readMessageEnd()" << endl
+          << endl;
+    } else {
+      out << indent() << "let args = try " << args_type << ".readValueFromProtocol(inProtocol)" << endl
+          << endl
+          << indent() << "try inProtocol.readMessageEnd()" << endl
+          << endl;
+    }
 
     if (!tfunction->is_oneway() ) {
       string result_type = function_result_helper_struct_type(tservice, tfunction);
@@ -1689,7 +2388,7 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
       if (!tfunction->get_returntype()->is_void()) {
         out << "result.success = ";
       }
-      out << "try handler." << function_name(tfunction) << "(";
+      out << "try handler." << (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()) << "(";
 
       t_struct* arg_struct = tfunction->get_arglist();
       const vector<t_field*>& fields = arg_struct->get_members();
@@ -1697,9 +2396,10 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
 
       for (f_iter = fields.begin(); f_iter != fields.end();) {
         string fieldName = (*f_iter)->get_name();
-        if (f_iter != fields.begin()) {
+        if (!gen_cocoa_ || f_iter != fields.begin()) {
           out << fieldName << ": ";
         }
+
         out << "args." << fieldName;
         if (++f_iter != fields.end()) {
           out << ", ";
@@ -1707,31 +2407,46 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
       }
 
       out << ")" << endl;
-
       block_close(out);
 
       t_struct* xs = tfunction->get_xceptions();
       const vector<t_field*>& xfields = xs->get_members();
       vector<t_field*>::const_iterator x_iter;
 
-      for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
-        indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name();
+      if (!gen_cocoa_) {
+        for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
+          indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name();
+          out << " { result." << (*x_iter)->get_name() << " = error }" << endl;
+        }
+
+        indent(out) << "catch let error { throw error }" << endl;
+        out << endl;
+
+        if (!tfunction->is_oneway()) {
+          out << indent() << "try outProtocol.writeMessageBegin(name: \"" << tfunction->get_name() << "\", type: .reply, sequenceID: sequenceID)" << endl
+              << indent() << "try result.write(to: outProtocol)" << endl
+              << indent() << "try outProtocol.writeMessageEnd()" << endl;
+        }
+      } else {
+        for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) {
+          indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name();
+          block_open(out);
+          indent(out) << "result." << (*x_iter)->get_name() << " = error" << endl;
+          block_close(out);
+        }
+
+        indent(out) << "catch let error";
         block_open(out);
-        indent(out) << "result." << (*x_iter)->get_name() << " = error" << endl;
+        out << indent() << "throw error" << endl;
         block_close(out);
-      }
 
-      indent(out) << "catch let error";
-      block_open(out);
-      out << indent() << "throw error" << endl;
-      block_close(out);
-
-      out << endl;
+        out << endl;
 
-      if (!tfunction->is_oneway()) {
-        out << indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << endl
-            << indent() << "try " << result_type << ".writeValue(result, toProtocol: outProtocol)" << endl
-            << indent() << "try outProtocol.writeMessageEnd()" << endl;
+        if (!tfunction->is_oneway()) {
+          out << indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << endl
+              << indent() << "try " << result_type << ".writeValue(result, toProtocol: outProtocol)" << endl
+              << indent() << "try outProtocol.writeMessageEnd()" << endl;
+        }
       }
     }
     block_close(out);
@@ -1742,14 +2457,16 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
 
   block_close(out,false);
   out << "()" << endl;
-
   out << endl;
 
-  indent(out) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws";
+  if (!gen_cocoa_) {
+    indent(out) << "public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws";
+  } else {
+    indent(out) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws";
+  }
   block_open(out);
 
   out << endl;
-
   out << indent() << "let (messageName, _, sequenceID) = try inProtocol.readMessageBegin()" << endl
       << endl
       << indent() << "if let processorHandler = " << name << ".processorHandlers[messageName]";
@@ -1758,29 +2475,43 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
   block_open(out);
   out << indent() << "try processorHandler(sequenceID, inProtocol, outProtocol, service)" << endl;
   block_close(out);
-  out << indent() << "catch let error as NSError";
-  block_open(out);
-  out << indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << endl;
-  block_close(out);
-  block_close(out);
-  out << indent() << "else";
-  block_open(out);
-  out << indent() << "try inProtocol.skipType(.STRUCT)" << endl
-      << indent() << "try inProtocol.readMessageEnd()" << endl
-      << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << endl;
-  indent_up();
-  out << indent() << "sequenceID: sequenceID," << endl
-      << indent() << "ex: NSError(" << endl;
-  indent_up();
-  out << indent() << "domain: TApplicationErrorDomain, " << endl
-      << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << endl
-      << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << endl;
-  indent_down();
-  indent_down();
-  block_close(out);
+  if (!gen_cocoa_) {
+    out << indent() << "catch let error as TApplicationError";
+    block_open(out);
+    out << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << endl;
+    block_close(out);
+    block_close(out);
+    out << indent() << "else";
+    block_open(out);
+    out << indent() << "try inProtocol.skip(type: .struct)" << endl
+        << indent() << "try inProtocol.readMessageEnd()" << endl
+        << indent() << "let ex = TApplicationError(error: .unknownMethod(methodName: messageName))" << endl
+        << indent() << "try outProtocol.writeException(messageName: messageName, "
+        << "sequenceID: sequenceID, ex: ex)" << endl;
+  } else {
+    out << indent() << "catch let error as NSError";
+    block_open(out);
+    out << indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << endl;
+    block_close(out);
+    block_close(out);
+    out << indent() << "else";
+    block_open(out);
+    out << indent() << "try inProtocol.skipType(.STRUCT)" << endl
+        << indent() << "try inProtocol.readMessageEnd()" << endl
+        << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << endl;
+    indent_up();
+    out << indent() << "sequenceID: sequenceID," << endl
+        << indent() << "ex: NSError(" << endl;
+    indent_up();
+    out << indent() << "domain: TApplicationErrorDomain, " << endl
+        << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << endl
+        << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << endl;
+    indent_down();
+    indent_down();
+  }
 
   block_close(out);
-
+  block_close(out);
   block_close(out);
   out << endl;
 }
@@ -1793,27 +2524,31 @@ void t_swift_generator::generate_swift_service_server_implementation(ofstream& o
  * @return Swift type name, i.e. Dictionary<Key,Value>
  */
 string t_swift_generator::type_name(t_type* ttype, bool is_optional, bool is_forced) {
-  string result;
+  string result = "";
+
   if (ttype->is_base_type()) {
-    result = base_type_name((t_base_type*)ttype);
+    result += base_type_name((t_base_type*)ttype);
   } else if (ttype->is_map()) {
     t_map *map = (t_map *)ttype;
-    result = "TMap<" + type_name(map->get_key_type()) + ", " + type_name(map->get_val_type()) + ">";
+    result += "TMap<" + type_name(map->get_key_type()) + ", " + type_name(map->get_val_type()) + ">";
   } else if (ttype->is_set()) {
     t_set *set = (t_set *)ttype;
-    result = "TSet<" + type_name(set->get_elem_type()) + ">";
+    result += "TSet<" + type_name(set->get_elem_type()) + ">";
   } else if (ttype->is_list()) {
     t_list *list = (t_list *)ttype;
-    result = "TList<" + type_name(list->get_elem_type()) + ">";
+    result += "TList<" + type_name(list->get_elem_type()) + ">";
   }
   else {
-    result = ttype->get_name();
+    t_program* program = ttype->get_program();
+    if (namespaced_ && program != program_) {
+      result += get_real_swift_module(program) + ".";
+    }
+    result += ttype->get_name();
   }
 
   if (is_optional) {
     result += "?";
   }
-
   if (is_forced) {
     result += "!";
   }
@@ -1834,7 +2569,7 @@ string t_swift_generator::base_type_name(t_base_type* type) {
     return "Void";
   case t_base_type::TYPE_STRING:
     if (type->is_binary()) {
-      return "TBinary";
+      return gen_cocoa_ ? "TBinary" : "Data";
     } else {
       return "String";
     }
@@ -1860,8 +2595,8 @@ string t_swift_generator::base_type_name(t_base_type* type) {
  *
  */
 void t_swift_generator::render_const_value(ostream& out,
-                                             t_type* type,
-                                             t_const_value* value) {
+                                           t_type* type,
+                                           t_const_value* value) {
   type = get_true_type(type);
 
   if (type->is_base_type()) {
@@ -1892,7 +2627,7 @@ void t_swift_generator::render_const_value(ostream& out,
       throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
     }
   } else if (type->is_enum()) {
-    out << value->get_identifier();
+    out << (gen_cocoa_ ? value->get_identifier() : enum_const_name(value->get_identifier())); // Swift2/Cocoa compatibility
   } else if (type->is_struct() || type->is_xception()) {
 
     out << type_name(type) << "(";
@@ -2003,17 +2738,22 @@ void t_swift_generator::render_const_value(ostream& out,
  */
 string t_swift_generator::declare_property(t_field* tfield, bool is_private) {
 
-  string visibility = is_private ? "private" : "public";
+  string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public";
 
   ostringstream render;
 
   render << visibility << " var " << maybe_escape_identifier(tfield->get_name());
 
   if (field_is_optional(tfield)) {
-    render << " : " << type_name(tfield->get_type(), true);
+    render << (gen_cocoa_ ? " " : "") << ": " << type_name(tfield->get_type(), true);
   }
   else {
-    render << " = " << type_name(tfield->get_type(), false) << "()";
+    if (!gen_cocoa_) {
+      render << ": " << type_name(tfield->get_type(), false);
+    } else {
+      // Swift2/Cocoa backward compat, Bad, default init
+      render << " = " << type_name(tfield->get_type(), false) << "()";
+    }
   }
 
   return render.str();
@@ -2027,9 +2767,9 @@ string t_swift_generator::declare_property(t_field* tfield, bool is_private) {
  */
 string t_swift_generator::function_signature(t_function* tfunction) {
 
-  string result = "func " + function_name(tfunction);
+  string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name());
 
-  result += "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws";
+  result += "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws"; /// argsreview
 
   t_type* ttype = tfunction->get_returntype();
   if (!ttype->is_void()) {
@@ -2040,6 +2780,110 @@ string t_swift_generator::function_signature(t_function* tfunction) {
 }
 
 /**
+ * Renders a function docstring
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+void t_swift_generator::function_docstring(ofstream& out, t_function* tfunction) {
+
+    // Generate docstring with following format:
+    // /// <Description>
+    // /// <empty line>
+    // /// - Parameters:
+    // ///   - <parameter>: <parameter docstring>
+    // /// - Returns: <return type> (Thrift has no docstring on return val)
+    // /// - Throws: <exception types>
+
+    // Description
+    string doc = tfunction->get_doc();
+    generate_docstring(out, doc);
+    indent(out) << "///" << endl;
+
+    // Parameters
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    if (!fields.empty()) {
+      indent(out) << "/// - Parameters:" << endl;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        indent(out) << "///   - " << (*f_iter)->get_name() << ": ";
+        string doc = (*f_iter)->get_doc();
+        if (!doc.empty() && doc[doc.length()-1] == '\n') {
+            doc.erase(doc.length()-1);
+        }
+        out << doc << endl;
+      }
+    }
+
+    // Returns
+    t_type* ttype = tfunction->get_returntype();
+    if (!ttype->is_void()) {
+      indent(out) << "/// - Returns: " << type_name(ttype) << endl;
+    }
+
+    // Throws
+    indent(out) << "/// - Throws: ";
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      out << type_name((*x_iter)->get_type());
+      if (*x_iter != xceptions.back()) {
+        out << ", ";
+      }    }
+    out << endl;
+}
+
+/**
+ * Renders a function docstring
+ *
+ * @param tfunction Function definition
+ * @return String of rendered function definition
+ */
+void t_swift_generator::async_function_docstring(ofstream& out, t_function* tfunction) {
+    // Generate docstring with following format:
+    // /// <Description>
+    // /// <empty line>
+    // /// - Parameters:
+    // ///   - <parameter>: <parameter docstring>
+    // ///   - callback: <callback types>
+
+    // Description
+    string doc = tfunction->get_doc();
+    generate_docstring(out, doc);
+    indent(out) << "///" << endl;
+
+    // Parameters
+    const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
+    vector<t_field*>::const_iterator f_iter;
+    if (!fields.empty()) {
+      indent(out) << "/// - Parameters:" << endl;
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        indent(out) << "///   - " << (*f_iter)->get_name() << ": ";
+        string doc = (*f_iter)->get_doc();
+        if (!doc.empty() && doc[doc.length()-1] == '\n') {
+            doc.erase(doc.length()-1);
+        }
+        out << doc << endl;
+      }
+    }
+
+    // completion
+    indent(out) << "///   - completion: TAsyncResult<" << type_name(tfunction->get_returntype())
+                << "> wrapping return and following Exceptions: ";
+    t_struct* xs = tfunction->get_xceptions();
+    const vector<t_field*>& xceptions = xs->get_members();
+    vector<t_field*>::const_iterator x_iter;
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      out << type_name((*x_iter)->get_type());
+      if (*x_iter != xceptions.back()) {
+        out << ", ";
+      }
+    }
+    out << endl;
+}
+
+/**
  * Renders a function signature that returns asynchronously via blocks.
  *
  * @param tfunction Function definition
@@ -2048,28 +2892,39 @@ string t_swift_generator::function_signature(t_function* tfunction) {
 string t_swift_generator::async_function_signature(t_function* tfunction) {
   t_type* ttype = tfunction->get_returntype();
   t_struct* targlist = tfunction->get_arglist();
-  string response_param = "(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ") -> Void";
-  string result = "func " + function_name(tfunction);
-  result += "(" + argument_list(tfunction->get_arglist(), "", false)
-          + (targlist->get_members().size() ? ", " : "")
-          + "success: " + response_param + ", "
-          + "failure: (NSError) -> Void) throws";
+  string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name());
+
+  if (!gen_cocoa_) {
+    string response_string = "(TAsyncResult<";
+    response_string += (ttype->is_void()) ? "Void" : type_name(ttype);
+    response_string += ">) -> Void";
+    result += "(" + argument_list(tfunction->get_arglist(), "", false)
+            + (targlist->get_members().size() ? ", " : "")
+            + "completion: @escaping " + response_string + ")";
+  } else {
+    string response_param = "(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ") -> Void";
+    result += "(" + argument_list(tfunction->get_arglist(), "", false)
+            + (targlist->get_members().size() ? ", " : "")
+            + "success: " + response_param + ", "
+            + "failure: (NSError) -> Void) throws";
+  }
   return result;
 }
 
 /**
  * Renders a function signature that returns asynchronously via promises.
+ * ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY
  *
  * @param tfunction Function definition
  * @return String of rendered function definition
  */
 string t_swift_generator::promise_function_signature(t_function* tfunction) {
   return "func " + function_name(tfunction) + "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws "
-          + "-> Promise<" + type_name(tfunction->get_returntype()) + ">";
+         + "-> Promise<" + type_name(tfunction->get_returntype()) + ">";
 }
 
 /**
- * Renders a verbose function name suitable for a Swift method
+ * Renders a verbose function name suitable for a Swift method.  ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY
  */
 string t_swift_generator::function_name(t_function* tfunction) {
   string name = tfunction->get_name();
@@ -2098,15 +2953,21 @@ string t_swift_generator::argument_list(t_struct* tstruct, string protocol_name,
     if (!fields.empty()) {
       result += ", ";
     }
-  }
-  else if (!fields.empty() && is_internal) {
-    // Force first argument to be named
+  } else if (!fields.empty() && is_internal && gen_cocoa_) {
+    // Force first argument to be named, Swift2/Cocoa backwards compat
     result += fields.front()->get_name() + " ";
   }
 
   for (f_iter = fields.begin(); f_iter != fields.end();) {
     t_field* arg = *f_iter;
-    result += arg->get_name() + ": " + type_name(arg->get_type());
+
+    if (!gen_cocoa_) {
+      // optional args not usually permitted for some reason, even though dynamic langs handle it
+      // use annotation "swift.nullable" to achieve
+      result += arg->get_name() + ": " + type_name(arg->get_type(), field_is_optional(arg));
+    } else {
+      result += arg->get_name() + ": " + type_name(arg->get_type());
+    }
 
     if (++f_iter != fields.end()) {
       result += ", ";
@@ -2121,31 +2982,118 @@ string t_swift_generator::argument_list(t_struct* tstruct, string protocol_name,
  */
 
 void t_swift_generator::populate_reserved_words() {
-  swift_reserved_words_.insert("Self");
-  swift_reserved_words_.insert("associatedtype");
-  swift_reserved_words_.insert("defer");
-  swift_reserved_words_.insert("deinit");
-  swift_reserved_words_.insert("dynamicType");
-  swift_reserved_words_.insert("enum");
-  swift_reserved_words_.insert("extension");
-  swift_reserved_words_.insert("fallthrough");
-  swift_reserved_words_.insert("false");
-  swift_reserved_words_.insert("func");
-  swift_reserved_words_.insert("guard");
-  swift_reserved_words_.insert("init");
-  swift_reserved_words_.insert("inout");
-  swift_reserved_words_.insert("internal");
-  swift_reserved_words_.insert("let");
-  swift_reserved_words_.insert("operator");
-  swift_reserved_words_.insert("protocol");
-  swift_reserved_words_.insert("repeat");
-  swift_reserved_words_.insert("rethrows");
-  swift_reserved_words_.insert("struct");
-  swift_reserved_words_.insert("subscript");
-  swift_reserved_words_.insert("throws");
-  swift_reserved_words_.insert("true");
-  swift_reserved_words_.insert("typealias");
-  swift_reserved_words_.insert("where");
+  if (!gen_cocoa_) {
+    swift_reserved_words_.insert("__COLUMN__");
+    swift_reserved_words_.insert("__FILE__");
+    swift_reserved_words_.insert("__FUNCTION__");
+    swift_reserved_words_.insert("__LINE__");
+    swift_reserved_words_.insert("Any");
+    swift_reserved_words_.insert("as");
+    swift_reserved_words_.insert("associatedtype");
+    swift_reserved_words_.insert("associativity");
+    swift_reserved_words_.insert("break");
+    swift_reserved_words_.insert("case");
+    swift_reserved_words_.insert("catch");
+    swift_reserved_words_.insert("class");
+    swift_reserved_words_.insert("continue");
+    swift_reserved_words_.insert("convenience");
+    swift_reserved_words_.insert("default");
+    swift_reserved_words_.insert("defer");
+    swift_reserved_words_.insert("deinit");
+    swift_reserved_words_.insert("didSet");
+    swift_reserved_words_.insert("do");
+    swift_reserved_words_.insert("dynamic");
+    swift_reserved_words_.insert("dynamicType");
+    swift_reserved_words_.insert("else");
+    swift_reserved_words_.insert("enum");
+    swift_reserved_words_.insert("extension");
+    swift_reserved_words_.insert("fallthrough");
+    swift_reserved_words_.insert("false");
+    swift_reserved_words_.insert("fileprivate");
+    swift_reserved_words_.insert("final");
+    swift_reserved_words_.insert("for");
+    swift_reserved_words_.insert("func");
+    swift_reserved_words_.insert("get");
+    swift_reserved_words_.insert("guard");
+    swift_reserved_words_.insert("if");
+    swift_reserved_words_.insert("import");
+    swift_reserved_words_.insert("in");
+    swift_reserved_words_.insert("indirect");
+    swift_reserved_words_.insert("infix");
+    swift_reserved_words_.insert("init");
+    swift_reserved_words_.insert("inout");
+    swift_reserved_words_.insert("internal");
+    swift_reserved_words_.insert("is");
+    swift_reserved_words_.insert("lazy");
+    swift_reserved_words_.insert("left");
+    swift_reserved_words_.insert("let");
+    swift_reserved_words_.insert("mutating");
+    swift_reserved_words_.insert("nil");
+    swift_reserved_words_.insert("none");
+    swift_reserved_words_.insert("nonmutating");
+    swift_reserved_words_.insert("open");
+    swift_reserved_words_.insert("operator");
+    swift_reserved_words_.insert("optional");
+    swift_reserved_words_.insert("override");
+    swift_reserved_words_.insert("postfix");
+    swift_reserved_words_.insert("precedence");
+    swift_reserved_words_.insert("prefix");
+    swift_reserved_words_.insert("private");
+    swift_reserved_words_.insert("protocol");
+    swift_reserved_words_.insert("Protocol");
+    swift_reserved_words_.insert("public");
+    swift_reserved_words_.insert("repeat");
+    swift_reserved_words_.insert("required");
+    swift_reserved_words_.insert("rethrows");
+    swift_reserved_words_.insert("return");
+    swift_reserved_words_.insert("right");
+    swift_reserved_words_.insert("self");
+    swift_reserved_words_.insert("Self");
+    swift_reserved_words_.insert("set");
+    swift_reserved_words_.insert("static");
+    swift_reserved_words_.insert("struct");
+    swift_reserved_words_.insert("subscript");
+    swift_reserved_words_.insert("super");
+    swift_reserved_words_.insert("switch");
+    swift_reserved_words_.insert("throw");
+    swift_reserved_words_.insert("throws");
+    swift_reserved_words_.insert("true");
+    swift_reserved_words_.insert("try");
+    swift_reserved_words_.insert("Type");
+    swift_reserved_words_.insert("typealias");
+    swift_reserved_words_.insert("unowned");
+    swift_reserved_words_.insert("var");
+    swift_reserved_words_.insert("weak");
+    swift_reserved_words_.insert("where");
+    swift_reserved_words_.insert("while");
+    swift_reserved_words_.insert("willSet");
+  } else {
+    swift_reserved_words_.insert("Self");
+    swift_reserved_words_.insert("associatedtype");
+    swift_reserved_words_.insert("defer");
+    swift_reserved_words_.insert("deinit");
+    swift_reserved_words_.insert("dynamicType");
+    swift_reserved_words_.insert("enum");
+    swift_reserved_words_.insert("extension");
+    swift_reserved_words_.insert("fallthrough");
+    swift_reserved_words_.insert("false");
+    swift_reserved_words_.insert("func");
+    swift_reserved_words_.insert("guard");
+    swift_reserved_words_.insert("init");
+    swift_reserved_words_.insert("inout");
+    swift_reserved_words_.insert("internal");
+    swift_reserved_words_.insert("let");
+    swift_reserved_words_.insert("operator");
+    swift_reserved_words_.insert("protocol");
+    swift_reserved_words_.insert("repeat");
+    swift_reserved_words_.insert("rethrows");
+    swift_reserved_words_.insert("struct");
+    swift_reserved_words_.insert("subscript");
+    swift_reserved_words_.insert("throws");
+    swift_reserved_words_.insert("true");
+    swift_reserved_words_.insert("typealias");
+    swift_reserved_words_.insert("where");
+  }
 }
 
 string t_swift_generator::maybe_escape_identifier(const string& identifier) {
@@ -2162,37 +3110,70 @@ string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
   type = get_true_type(type);
 
   string result = qualified ? "TType." : ".";
-
-  if (type->is_base_type()) {
-    t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-    switch (tbase) {
-    case t_base_type::TYPE_VOID:
-      throw "NO T_VOID CONSTRUCT";
-    case t_base_type::TYPE_STRING:
-      return result + "STRING";
-    case t_base_type::TYPE_BOOL:
-      return result + "BOOL";
-    case t_base_type::TYPE_I8:
-      return result + "BYTE";
-    case t_base_type::TYPE_I16:
-      return result + "I16";
-    case t_base_type::TYPE_I32:
+  if (!gen_cocoa_) {
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+        case t_base_type::TYPE_VOID:
+          throw "NO T_VOID CONSTRUCT";
+        case t_base_type::TYPE_STRING:
+          return result + "string";
+        case t_base_type::TYPE_BOOL:
+          return result + "bool";
+        case t_base_type::TYPE_I8:
+          return result + "i8";
+        case t_base_type::TYPE_I16:
+          return result + "i16";
+        case t_base_type::TYPE_I32:
+          return result + "i32";
+        case t_base_type::TYPE_I64:
+          return result + "i64";
+        case t_base_type::TYPE_DOUBLE:
+          return result + "double";
+      }
+    } else if (type->is_enum()) {
+      return result + "i32";
+    } else if (type->is_struct() || type->is_xception()) {
+      return result + "struct";
+    } else if (type->is_map()) {
+      return result + "map";
+    } else if (type->is_set()) {
+      return result + "set";
+    } else if (type->is_list()) {
+      return result + "list";
+    }
+  } else {
+    if (type->is_base_type()) {
+      t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+      switch (tbase) {
+        case t_base_type::TYPE_VOID:
+          throw "NO T_VOID CONSTRUCT";
+        case t_base_type::TYPE_STRING:
+          return result + "STRING";
+        case t_base_type::TYPE_BOOL:
+          return result + "BOOL";
+        case t_base_type::TYPE_I8:
+          return result + "BYTE";
+        case t_base_type::TYPE_I16:
+          return result + "I16";
+        case t_base_type::TYPE_I32:
+          return result + "I32";
+        case t_base_type::TYPE_I64:
+          return result + "I64";
+        case t_base_type::TYPE_DOUBLE:
+          return result + "DOUBLE";
+      }
+    } else if (type->is_enum()) {
       return result + "I32";
-    case t_base_type::TYPE_I64:
-      return result + "I64";
-    case t_base_type::TYPE_DOUBLE:
-      return result + "DOUBLE";
+    } else if (type->is_struct() || type->is_xception()) {
+      return result + "STRUCT";
+    } else if (type->is_map()) {
+      return result + "MAP";
+    } else if (type->is_set()) {
+      return result + "SET";
+    } else if (type->is_list()) {
+      return result + "LIST";
     }
-  } else if (type->is_enum()) {
-    return result + "I32";
-  } else if (type->is_struct() || type->is_xception()) {
-    return result + "STRUCT";
-  } else if (type->is_map()) {
-    return result + "MAP";
-  } else if (type->is_set()) {
-    return result + "SET";
-  } else if (type->is_list()) {
-    return result + "LIST";
   }
 
   throw "INVALID TYPE IN type_to_enum: " + type->get_name();
@@ -2201,9 +3182,12 @@ string t_swift_generator::type_to_enum(t_type* type, bool qualified) {
 
 THRIFT_REGISTER_GENERATOR(
     swift,
-    "Swift",
+    "Swift 3.0",
     "    log_unexpected:  Log every time an unexpected field ID or type is encountered.\n"
     "    debug_descriptions:\n"
     "                     Allow use of debugDescription so the app can add description via a cateogory/extension\n"
     "    async_clients:   Generate clients which invoke asynchronously via block syntax.\n"
-    "    promise_kit:     Generate clients which invoke asynchronously via promises.\n")
+    "    namespaced:      Generate source in Module scoped output directories for Swift Namespacing.\n"
+    "    cocoa:           Generate Swift 2.x code compatible with the Thrift/Cocoa library\n"
+    "    promise_kit:     Generate clients which invoke asynchronously via promises (only use with cocoa flag)\n"
+    "    safe_enums:      Generate enum types with an unknown case to handle unspecified values rather than throw a serialization error\n")
diff --git a/lib/swift/Package.swift b/lib/swift/Package.swift
new file mode 100644
index 0000000..b533f60
--- /dev/null
+++ b/lib/swift/Package.swift
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import PackageDescription
+
+let package = Package(
+	name: "Thrift"
+)
diff --git a/lib/swift/README.md b/lib/swift/README.md
new file mode 100644
index 0000000..50f522d
--- /dev/null
+++ b/lib/swift/README.md
@@ -0,0 +1,215 @@
+Thrift Swift Library
+=========================
+
+License
+-------
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+
+
+## Build
+
+    swift build
+
+## Test
+    swift test
+
+## Install Library
+##### Cocoapods
+Add the following to your podfile
+```ruby
+    pod 'Thrift-swift3', :git => 'git@github.com:apache/thrift.git', :branch => 'master'
+```
+
+##### SPM
+Unfortunately due to some limitations in SPM, the Package manifest and Sources directory must be at the root of the project.
+To get around that for the time being, you can use this mirrored repo.
+Add the following to your Package.swift
+```swift
+dependencies: [
+    .Package(url: "https://github.com/apocolipse/Thrift-Swift.git", majorVersion: 1)
+]
+```
+
+## Thrift Compiler
+
+You can compile IDL sources for Swift 3 with the following command:
+
+    thrift --gen swift thrift_file
+
+## Client Example
+```swift
+let transport = TSocketTransport(hostname: "localhost", port: 9090)!
+
+//  var proto = TCompactProtocol(transport: transport)
+let proto = TBinaryProtocol(on: transport)
+//  var client = HermesClient(inoutProtocol: proto)
+let client = ThriftTestClient(inoutProtocol: proto)
+do {
+    try client.testVoid()
+} catch let error {
+    print("\(error)")
+}
+```
+
+## Library Notes
+- Eliminated Protocol Factories, They were only used in async clients and server implementations, where Generics provide a better alternative.
+- Swifty Errors, All `TError` types have a nested `ErrorCode` Enum as well as some extra flavor where needed.
+- Value typed everything.  `TTransport` operates on value typed `Data` rather than reference typed `NSData` or `UnsafeBufferPointer`s
+- Swift 3 Named protocols.  Swift 3 naming conventions suggest the elimination of redundant words that can be inferred from variable/function signatures.  This renaming is applied throughout the Swift 3 library converting most naming conventions used in the Swift2/Cocoa library to Swift 3-esque naming conventions. eg.
+```swift
+func readString() throws -> String
+func writeString(_ val: String) throws
+```
+have been renamed to eliminate redundant words:
+```swift
+func read() throws -> String
+func write(_ val: String) throws
+```
+
+- Eliminated `THTTPTransport` that uses `NSURLConnection` due to it being deprecated and not available at all in Swift 3 for Linux.  `THTTPSessionTransport` from the Swift2/Cocoa library that uses `NSURLSession` has been renamed to `THTTPTransport` for this library and leverages `URLSession`, providing both synchronous (with semaphores) and asynchronous behavior.
+- Probably some More things I've missed here.
+
+## Generator Notes
+#### Generator Flags
+| Flag          | Description           |
+| ------------- |:-------------:|
+| async_clients | Generate clients which invoke asynchronously via block syntax.Asynchronous classes are appended with `_Async` |
+| no_strict*    | Generates non-strict structs      |
+| debug_descriptions | Allow use of debugDescription so the app can add description via a cateogory/extension      |
+| log_unexpected | Log every time an unexpected field ID or type is encountered. |
+
+
+
+*Most thrift libraries allow empty initialization of Structs, initializing `required` fields with nil/null/None (Python and Node generators).  Swift on the other hand requires initializers to initialize all non-Optional fields, and thus the Swift 3 generator does not provide default values (unlike the Swift 2/Cocoa generator).  In other languages, this allows the sending of NULL values in fields that are marked `required`, and thus will throw an error in Swift clients attempting to valid [...]
+
+
+## Whats implemented
+#### Library
+##### Transports
+- [x] TSocketTransport - CFSocket and PosixSocket variants available. CFSocket variant only currently available for Darwin platforms
+- [x] THTTPTransport - Currently only available for Darwin platforms, Swift Foundation URLSession implementation needs completion on linux.
+- [x] TSocketServer - Uses CFSockets only for binding, should be working on linux
+- [x] TFramedTransport
+- [x] TMemoryBufferTransport
+- [x] TFileTransport - A few variants using File handles and file descriptors.
+- [x] TStreamTransport - Fully functional in Darwin, Foundation backing not yet completed in Linux (This limits TCFSocketTransport to Darwin)
+- [ ] HTTPServer - Currently there is no lightweight  HTTPServer implementation the Swift Standard Library, so other 3rd party alternatives are required and out of scope for the Thrift library.  Examples using Perfect will be provided.
+- [ ] Other (gz, etc)
+
+##### Protocols
+- [x] TBinaryProtocol
+- [x] TCompactProtocol
+- [ ] TJSONProtocol - This will need to be implemented
+
+##### Generator
+- [x] Code Complete Generator
+- [x] Async clients
+- [x] Documentation Generation - Generator will transplant IDL docs to Swift code for easy lookup in Xcode
+- [ ] Default Values - TODO
+- [ ] no_strict mode - TODO
+- [ ] Namespacing - Still haven't nailed down a good paradigm for namespacing.  It will likely involve creating subdirectories for different namespaces and expecting the developer to import each subdirectory as separate modules.  It could extend to creating SPM Package manifests with sub-modules within the generated module
+
+
+
+## Example HTTP Server with Perfect
+```swift
+import PerfectLib
+import PerfectHTTP
+import PerfectHTTPServer
+import Dispatch
+
+let logQueue = DispatchQueue(label: "log", qos: .background, attributes: .concurrent)
+let pQueue = DispatchQueue(label: "log", qos: .userInitiated, attributes: .concurrent)
+
+
+class TPerfectServer<InProtocol: TProtocol, OutProtocol: TProtocol> {
+
+ private var server = HTTPServer()
+ private var processor: TProcessor
+
+ init(address: String? = nil,
+      path: String? = nil,
+      port: Int,
+      processor: TProcessor,
+      inProtocol: InProtocol.Type,
+      outProtocol: OutProtocol.Type) throws {
+
+   self.processor = processor
+
+   if let address = address {
+     server.serverAddress = address
+   }
+   server.serverPort = UInt16(port)
+
+   var routes = Routes()
+   var uri = "/"
+   if let path = path {
+     uri += path
+   }
+   routes.add(method: .post, uri: uri) { request, response in
+     pQueue.async {
+       response.setHeader(.contentType, value: "application/x-thrift")
+
+       let itrans = TMemoryBufferTransport()
+       if let bytes = request.postBodyBytes {
+         let data = Data(bytes: bytes)
+         itrans.reset(readBuffer: data)
+       }
+
+       let otrans = TMemoryBufferTransport(flushHandler: { trans, buff in
+         let array = buff.withUnsafeBytes {
+           Array<UInt8>(UnsafeBufferPointer(start: $0, count: buff.count))
+         }
+         response.status = .ok
+         response.setBody(bytes: array)
+         response.completed()
+       })
+
+       let inproto = InProtocol(on: itrans)
+       let outproto = OutProtocol(on: otrans)
+
+       do {
+         try processor.process(on: inproto, outProtocol: outproto)
+         try otrans.flush()
+       } catch {
+         response.status = .badRequest
+         response.completed()
+       }
+     }
+   }
+   server.addRoutes(routes)
+ }
+
+ func serve() throws {
+   try server.start()
+ }
+}
+```
+
+#### Example Usage
+```swift
+class ServiceHandler : Service {
+    ...
+}
+let server = try? TPerfectServer(port: 9090,
+                                processor: ServiceProcessor(service: ServiceHandler()),
+                                inProtocol: TBinaryProtocol.self,
+                                outProtocol: TBinaryProtocol.self)
+
+try? server?.serve()
+```
diff --git a/lib/swift/Sources/LinuxHelper.swift b/lib/swift/Sources/LinuxHelper.swift
new file mode 100644
index 0000000..66d92bb
--- /dev/null
+++ b/lib/swift/Sources/LinuxHelper.swift
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import Foundation
+import CoreFoundation
+
+#if os(Linux)
+/// Extensions for Linux for incomplete Foundation API's.
+/// swift-corelibs-foundation is not yet 1:1 with OSX/iOS Foundation
+
+extension CFSocketError {
+  public static let success = kCFSocketSuccess
+}
+  
+extension UInt {
+  public static func &(lhs: UInt, rhs: Int) -> UInt {
+    let cast = unsafeBitCast(rhs, to: UInt.self)
+    return lhs & cast
+  }
+}
+
+#else
+extension CFStreamPropertyKey {
+  static let shouldCloseNativeSocket  = CFStreamPropertyKey(kCFStreamPropertyShouldCloseNativeSocket)
+  // Exists as Stream.PropertyKey.socketSecuritylevelKey but doesn't work with CFReadStreamSetProperty
+  static let socketSecurityLevel      = CFStreamPropertyKey(kCFStreamPropertySocketSecurityLevel)
+  static let SSLSettings              = CFStreamPropertyKey(kCFStreamPropertySSLSettings)
+}
+#endif
diff --git a/lib/swift/Sources/TApplicationError.swift b/lib/swift/Sources/TApplicationError.swift
new file mode 100644
index 0000000..bc39396
--- /dev/null
+++ b/lib/swift/Sources/TApplicationError.swift
@@ -0,0 +1,157 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+public struct TApplicationError : TError {
+  public enum Code : TErrorCode {
+    case unknown
+    case unknownMethod(methodName: String?)
+    case invalidMessageType
+    case wrongMethodName(methodName: String?)
+    case badSequenceId
+    case missingResult(methodName: String?)
+    case internalError
+    case protocolError
+    case invalidTransform
+    case invalidProtocol
+    case unsupportedClientType
+    
+    
+    /// Initialize a TApplicationError with a Thrift error code
+    /// Normally this would be achieved with RawRepresentable however
+    /// by doing this we can allow for associated properties on enum cases for
+    /// case specific context data in a Swifty, type-safe manner.
+    ///
+    /// - parameter thriftErrorCode: Integer TApplicationError(exception) error code.  
+    ///                              Default to 0 (.unknown)
+    public init(thriftErrorCode: Int) {
+      switch thriftErrorCode {
+      case 1:  self = .unknownMethod(methodName: nil)
+      case 2:  self = .invalidMessageType
+      case 3:  self = .wrongMethodName(methodName: nil)
+      case 4:  self = .badSequenceId
+      case 5:  self = .missingResult(methodName: nil)
+      case 6:  self = .internalError
+      case 7:  self = .protocolError
+      case 8:  self = .invalidProtocol
+      case 9:  self = .invalidTransform
+      case 10: self = .unsupportedClientType
+      default: self = .unknown
+      }
+    }
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:                return 0
+      case .unknownMethod:          return 1
+      case .invalidMessageType:     return 2
+      case .wrongMethodName:        return 3
+      case .badSequenceId:          return 4
+      case .missingResult:          return 5
+      case .internalError:          return 6
+      case .protocolError:          return 7
+      case .invalidProtocol:        return 8
+      case .invalidTransform:       return 9
+      case .unsupportedClientType:  return 10
+      }
+    }
+    
+    public var description: String {
+      /// Output "for #methodName" if method is not nil else empty
+      let methodUnwrap: (String?) -> String =  { method in
+        return "\(method == nil ? "" : " for \(method ?? "")")"
+      }
+      switch self {
+      case .unknown:                      return "Unknown TApplicationError"
+      case .unknownMethod(let method):    return "Unknown Method\(methodUnwrap(method))"
+      case .invalidMessageType:           return "Invalid Message Type"
+      case .wrongMethodName(let method):  return "Wrong Method Name\(methodUnwrap(method))"
+      case .badSequenceId:                return "Bad Sequence ID"
+      case .missingResult(let method):    return "Missing Result\(methodUnwrap(method))"
+      case .internalError:                return "Internal Error"
+      case .protocolError:                return "Protocol Error"
+      case .invalidProtocol:              return "Invalid Protocol"
+      case .invalidTransform:             return "Invalid Transform"
+      case .unsupportedClientType:        return "Unsupported Client Type"
+      }
+    }
+  }
+
+  public init() { }
+  
+  public init(thriftErrorCode code: Int, message: String? = nil) {
+    self.error = Code(thriftErrorCode: code)
+    self.message = message
+  }
+  
+  public var error: Code = .unknown
+  public var message: String? = nil
+  public static var defaultCase: Code { return .unknown }
+}
+
+extension TApplicationError : TSerializable {
+  public static var thriftType: TType { return .struct }
+  
+  public static func read(from proto: TProtocol) throws -> TApplicationError {
+    var errorCode: Int = 0
+    var message: String? = nil
+    _ = try proto.readStructBegin()
+    fields: while true {
+      let (_, fieldType, fieldID) = try proto.readFieldBegin()
+      
+      switch (fieldID, fieldType) {
+      case (_, .stop):
+        break fields
+      case (1, .string):
+        message = try proto.read()
+      case (2, .i32):
+        errorCode = Int(try proto.read() as Int32)
+      
+      case let (_, unknownType):
+        try proto.skip(type: unknownType)
+      }
+      
+      try proto.readFieldEnd()
+    }
+    try proto.readStructEnd()
+    return TApplicationError(thriftErrorCode: errorCode, message: message)
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.writeStructBegin(name: "TApplicationException")
+    
+    try proto.writeFieldBegin(name: "message", type: .string, fieldID: 1)
+    try proto.write(message ?? "")
+    try proto.writeFieldEnd()
+    
+    try proto.writeFieldBegin(name: "type", type: .i32, fieldID: 2)
+    let val = Int32(error.thriftErrorCode)
+    try proto.write(val)
+    try proto.writeFieldEnd()
+    try proto.writeFieldStop()
+    try proto.writeStructEnd()
+  }
+  
+  public var hashValue: Int {
+    return error.thriftErrorCode &+ (message?.hashValue ?? 0)
+  }
+}
+
+public func ==(lhs: TApplicationError, rhs: TApplicationError) -> Bool {
+  return lhs.error.thriftErrorCode == rhs.error.thriftErrorCode && lhs.message == rhs.message
+}
diff --git a/lib/swift/Sources/TBinary.swift b/lib/swift/Sources/TBinary.swift
new file mode 100644
index 0000000..4be5644
--- /dev/null
+++ b/lib/swift/Sources/TBinary.swift
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+extension Data : TSerializable {
+  public static var thriftType: TType { return .string }
+  
+  public static func read(from proto: TProtocol) throws -> Data {
+    return try proto.read() as Data
+  }
+  
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
diff --git a/lib/swift/Sources/TBinaryProtocol.swift b/lib/swift/Sources/TBinaryProtocol.swift
new file mode 100644
index 0000000..47f3f28
--- /dev/null
+++ b/lib/swift/Sources/TBinaryProtocol.swift
@@ -0,0 +1,384 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+public struct TBinaryProtocolVersion {
+  static let version1    = Int32(bitPattern: 0x80010000)
+  static let versionMask = Int32(bitPattern: 0xffff0000)
+}
+
+public class TBinaryProtocol: TProtocol {
+  public var messageSizeLimit: UInt32  = 0
+  
+  public var transport: TTransport
+  
+  // class level properties for setting global config (useful for server in lieu of Factory design)
+  public static var strictRead: Bool = false
+  public static var strictWrite: Bool = true
+
+  private var strictRead: Bool
+  private var strictWrite: Bool
+  
+  var currentMessageName: String?
+  var currentFieldName: String?
+  
+  
+  public convenience init(transport: TTransport, strictRead: Bool, strictWrite: Bool) {
+    self.init(on: transport)
+    self.strictRead = strictRead
+    self.strictWrite = strictWrite
+  }
+  
+  public required init(on transport: TTransport) {
+    self.transport = transport
+    self.strictWrite = TBinaryProtocol.strictWrite
+    self.strictRead = TBinaryProtocol.strictRead
+  }
+  
+  func readStringBody(_ size: Int) throws -> String {
+    
+    var data = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport read failed")) {
+      data = try self.transport.readAll(size: size)
+    }
+    
+    return String(data: data, encoding: String.Encoding.utf8) ?? ""
+  }
+  
+  /// Mark: - TProtocol
+  
+  public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+    let size: Int32 = try read()
+    var messageName = ""
+    var type = TMessageType.exception
+    
+    if size < 0 {
+      let version = size & TBinaryProtocolVersion.versionMask
+      if version != TBinaryProtocolVersion.version1 {
+        throw TProtocolError(error: .badVersion(expected: "\(TBinaryProtocolVersion.version1)",
+                                                got: "\(version)"))
+      }
+      type = TMessageType(rawValue: Int32(size) & 0x00FF) ?? type
+      messageName = try read()
+    } else {
+      if strictRead {
+        let errorMessage = "Missing message version, old client? Message Name: \(currentMessageName)"
+        throw TProtocolError(error: .invalidData,
+                             message: errorMessage)
+      }
+      if messageSizeLimit > 0 && size > Int32(messageSizeLimit) {
+        throw TProtocolError(error: .sizeLimit(limit: Int(messageSizeLimit), got: Int(size)))
+      }
+      
+      messageName = try readStringBody(Int(size))
+      type = TMessageType(rawValue: Int32(try read() as UInt8)) ?? type
+    }
+    
+    let seqID: Int32 = try read()
+    return (messageName, type, seqID)
+  }
+  
+  public func readMessageEnd() throws {
+    return
+  }
+  
+  public func readStructBegin() throws -> String {
+    return ""
+  }
+  
+  public func readStructEnd() throws {
+    return
+  }
+  
+  public func readFieldBegin() throws -> (String, TType, Int32) {
+    
+    let fieldType = TType(rawValue: Int32(try read() as UInt8)) ?? TType.stop
+    var fieldID: Int32 = 0
+    
+    if fieldType != .stop {
+      fieldID = Int32(try read() as Int16)
+    }
+    
+    return ("", fieldType, fieldID)
+  }
+  
+  public func readFieldEnd() throws {
+    return
+  }
+  
+  public func readMapBegin() throws -> (TType, TType, Int32) {
+    var raw = Int32(try read() as UInt8)
+    guard let keyType = TType(rawValue: raw) else {
+      throw TProtocolError(message: "Unknown value for keyType TType: \(raw)")
+    }
+    
+    raw = Int32(try read() as UInt8)
+    guard let valueType = TType(rawValue: raw) else {
+      throw TProtocolError(message: "Unknown value for valueType TType: \(raw)")
+    }
+    let size: Int32 = try read()
+    
+    return (keyType, valueType, size)
+  }
+  
+  public func readMapEnd() throws {
+    return
+  }
+  
+  public func readSetBegin() throws -> (TType, Int32) {
+    let raw = Int32(try read() as UInt8)
+    guard let elementType = TType(rawValue: raw) else {
+      throw TProtocolError(message: "Unknown value for elementType TType: \(raw)")
+    }
+    
+    let size: Int32 = try read()
+    
+    return (elementType, size)
+  }
+  
+  public func readSetEnd() throws {
+    return
+  }
+  
+  public func readListBegin() throws -> (TType, Int32) {
+    let raw = Int32(try read() as UInt8)
+    guard let elementType = TType(rawValue: raw) else {
+      throw TProtocolError(message: "Unknown value for elementType TType: \(raw)")
+    }
+    let size: Int32 = try read()
+    
+    return (elementType, size)
+  }
+  
+  public func readListEnd() throws {
+    return
+  }
+  
+  public func read() throws -> String {
+    let data: Data = try read()
+    guard let str = String.init(data: data, encoding: .utf8) else {
+      throw TProtocolError(error: .invalidData, message: "Couldn't encode UTF-8 from data read")
+    }
+    return str
+  }
+  
+  public func read() throws -> Bool {
+    return (try read() as UInt8) == 1
+  }
+  
+  public func read() throws -> UInt8 {
+    var buff = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 1)
+    }
+    return buff[0]
+  }
+  
+  public func read() throws -> Int16 {
+    var buff = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 2)
+    }
+    var ret = Int16(buff[0] & 0xff) << 8
+    ret |=    Int16(buff[1] & 0xff)
+    return ret
+  }
+  
+  public func read() throws -> Int32 {
+    var buff = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 4)
+    }
+    var ret = Int32(buff[0] & 0xff) << 24
+    ret |=    Int32(buff[1] & 0xff) << 16
+    ret |=    Int32(buff[2] & 0xff) << 8
+    ret |=    Int32(buff[3] & 0xff)
+    
+    return ret
+  }
+  
+  public func read() throws -> Int64 {
+    var buff = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 8)
+    }
+    var ret = Int64(buff[0] & 0xff) << 56
+    ret |=    Int64(buff[1] & 0xff) << 48
+    ret |=    Int64(buff[2] & 0xff) << 40
+    ret |=    Int64(buff[3] & 0xff) << 32
+    ret |=    Int64(buff[4] & 0xff) << 24
+    ret |=    Int64(buff[5] & 0xff) << 16
+    ret |=    Int64(buff[6] & 0xff) << 8
+    ret |=    Int64(buff[7] & 0xff)
+    
+    return ret
+  }
+  
+  public func read() throws -> Double {
+    let val = try read() as Int64
+    return unsafeBitCast(val, to: Double.self)
+  }
+  
+  public func read() throws -> Data {
+    let size = Int(try read() as Int32)
+    var data = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      data = try self.transport.readAll(size: size)
+    }
+    
+    return data
+  }
+  
+  // Write methods
+  
+  public func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws {
+    if strictWrite {
+      let version = TBinaryProtocolVersion.version1 | Int32(messageType.rawValue)
+      try write(version)
+      try write(name)
+      try write(sequenceID)
+    } else {
+      try write(name)
+      try write(UInt8(messageType.rawValue))
+      try write(sequenceID)
+    }
+    currentMessageName = name
+  }
+  
+  public func writeMessageEnd() throws {
+    currentMessageName = nil
+  }
+  
+  public func writeStructBegin(name: String) throws {
+    return
+  }
+  
+  public func writeStructEnd() throws {
+    return
+  }
+  
+  public func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws {
+    try write(UInt8(fieldType.rawValue))
+    try write(Int16(fieldID))
+  }
+  
+  public func writeFieldStop() throws {
+    try write(UInt8(TType.stop.rawValue))
+  }
+  
+  public func writeFieldEnd() throws {
+    return
+  }
+  
+  public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+    try write(UInt8(keyType.rawValue))
+    try write(UInt8(valueType.rawValue))
+    try write(size)
+  }
+  
+  public func writeMapEnd() throws {
+    return
+  }
+  
+  public func writeSetBegin(elementType: TType, size: Int32) throws {
+    try write(UInt8(elementType.rawValue))
+    try write(size)
+  }
+  
+  public func writeSetEnd() throws {
+    return
+  }
+  
+  public func writeListBegin(elementType: TType, size: Int32) throws {
+    try write(UInt8(elementType.rawValue))
+    try write(size)
+  }
+  
+  public func writeListEnd() throws {
+    return
+  }
+  
+  public func write(_ value: String) throws {
+    try write(value.data(using: .utf8)!)
+  }
+  
+  public func write(_ value: Bool) throws {
+    let byteVal: UInt8 = value ? 1 : 0
+    try write(byteVal)
+  }
+  
+  public func write(_ value: UInt8) throws {
+    let buff = Data(bytes: [value])
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+      try self.transport.write(data: buff)
+    }
+  }
+  
+  public func write(_ value: Int16) throws {
+    var buff = Data()
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+      try self.transport.write(data: buff)
+    }
+  }
+  
+  public func write(_ value: Int32) throws {
+    var buff = Data()
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 24))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 16))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+      try self.transport.write(data: buff)
+    }
+  }
+  
+  public func write(_ value: Int64) throws {
+    var buff = Data()
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 56))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 48))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 40))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 32))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 24))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 16))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value >> 8))]))
+    buff.append(Data(bytes: [UInt8(0xff & (value))]))
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+      try self.transport.write(data: buff)
+    }
+  }
+  
+  public func write(_ value: Double) throws {
+    // Notably unsafe, since Double and Int64 are the same size, this should work fine
+    try self.write(unsafeBitCast(value, to: Int64.self))
+  }
+  
+  public func write(_ data: Data) throws {
+    try write(Int32(data.count))
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) {
+      try self.transport.write(data: data)
+    }
+  }
+}
diff --git a/lib/swift/Sources/TClient.swift b/lib/swift/Sources/TClient.swift
new file mode 100644
index 0000000..c404c9a
--- /dev/null
+++ b/lib/swift/Sources/TClient.swift
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+open class TClient {
+  public let inProtocol: TProtocol
+  public let outProtocol: TProtocol
+
+  public init(inoutProtocol: TProtocol) {
+    self.inProtocol = inoutProtocol
+    self.outProtocol = inoutProtocol
+  }
+
+  public init(inProtocol: TProtocol, outProtocol: TProtocol) {
+    self.inProtocol = inProtocol
+    self.outProtocol = outProtocol
+  }
+}
+
+
+open class TAsyncClient<Protocol: TProtocol, Factory: TAsyncTransportFactory> {
+  public var factory: Factory
+  public init(with protocol: Protocol.Type, factory: Factory) {
+    self.factory = factory
+  }
+}
+
+
+public enum TAsyncResult<T> {
+  case success(T)
+  case error(Swift.Error)
+  
+  public func value() throws -> T {
+    switch self {
+    case .success(let t): return t
+    case .error(let e): throw e
+    }
+  }
+}
diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift
new file mode 100644
index 0000000..ac5b35a
--- /dev/null
+++ b/lib/swift/Sources/TCompactProtocol.swift
@@ -0,0 +1,575 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+import CoreFoundation
+
+public enum TCType: UInt8 {
+  case stop          = 0x00
+  case boolean_TRUE  = 0x01
+  case boolean_FALSE = 0x02
+  case i8            = 0x03
+  case i16           = 0x04
+  case i32           = 0x05
+  case i64           = 0x06
+  case double        = 0x07
+  case binary        = 0x08
+  case list          = 0x09
+  case set           = 0x0A
+  case map           = 0x0B
+  case `struct`      = 0x0C
+  
+  public static let typeMask: UInt8 = 0xE0 // 1110 0000
+  public static let typeBits: UInt8 = 0x07 // 0000 0111
+  public static let typeShiftAmount = 5
+ 
+}
+
+
+public class TCompactProtocol: TProtocol {
+  public static let protocolID: UInt8  = 0x82
+  public static let version: UInt8     = 1
+  public static let versionMask: UInt8 = 0x1F // 0001 1111
+  
+  public var transport: TTransport
+  
+  var lastField: [UInt8] = []
+  var lastFieldId: UInt8 = 0
+  
+  var boolFieldName: String?
+  var boolFieldType: TType?
+  var boolFieldId: Int32?
+  var booleanValue: Bool?
+  
+  var currentMessageName: String?
+
+  public required init(on transport: TTransport) {
+    self.transport = transport
+  }
+
+  
+  /// Mark: - TCompactProtocol helpers
+  
+  func writebyteDirect(_ byte: UInt8) throws {
+    let byte = Data(bytes: [byte])
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+      try self.transport.write(data: byte)
+    }
+  }
+  
+  func writeVarint32(_ val: UInt32) throws {
+    var val = val
+    var i32buf = [UInt8](repeating: 0, count: 5)
+    var idx = 0
+    while true {
+      if (val & ~0x7F) == 0 {
+        i32buf[idx] = UInt8(val)
+        idx += 1
+        break
+      } else {
+        i32buf[idx] = UInt8((val & 0x7F) | 0x80)
+        idx += 1
+        val >>= 7
+      }
+    }
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+      try self.transport.write(data: Data(bytes: i32buf[0..<idx]))
+    }
+  }
+  
+  func writeVarint64(_ val: UInt64) throws {
+    var val = val
+    var varint64out = [UInt8](repeating: 0, count: 10)
+    var idx = 0
+    while true {
+      if (val & ~0x7F) == 0{
+        varint64out[idx] = UInt8(val)
+        idx += 1
+        break
+      } else {
+        varint64out[idx] = UInt8(val & 0x7F) | 0x80
+        idx += 1
+        val >>= 7
+      }
+    }
+    
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+      try self.transport.write(data: Data(bytes: varint64out[0..<idx]))
+    }
+  
+  }
+  
+  func writeCollectionBegin(_ elementType: TType, size: Int32) throws {
+    let ctype = compactType(elementType).rawValue
+    if size <= 14 {
+      try writebyteDirect(UInt8(size << 4) | ctype)
+    } else {
+      try writebyteDirect(0xF0 | ctype)
+      try writeVarint32(UInt32(size))
+    }
+  }
+  
+  func readBinary(_ size: Int) throws -> Data {
+    var result = Data()
+    if size != 0 {
+      try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+        result = try self.transport.readAll(size: size)
+      }
+    }
+    return result
+  }
+  
+  func readVarint32() throws -> UInt32 {
+    var result: UInt32 = 0
+    var shift: UInt32 = 0
+    while true {
+      let byte: UInt8 = try read()
+      
+      result |= UInt32(byte & 0x7F) << shift
+      if (byte & 0x80) == 0 {
+        break
+      }
+      
+      shift += 7
+    }
+    
+    return result
+  }
+  
+  func readVarint64() throws -> UInt64 {
+    var result: UInt64 = 0
+    var shift: UInt64 = 0
+    
+    while true {
+      let byte: UInt8 = try read()
+      
+      result |= UInt64(byte & 0x7F) << shift
+      if (byte & 0x80) == 0 {
+        break
+      }
+      
+      shift += 7
+    }
+    return result
+  }
+  
+
+  func ttype(_ compactTypeVal: UInt8) throws -> TType {
+    guard let compactType = TCType(rawValue: compactTypeVal) else {
+      throw TProtocolError(message: "Unknown TCType value: \(compactTypeVal)")
+    }
+    
+    switch compactType {
+    case .stop: return .stop;
+    case .boolean_FALSE, .boolean_TRUE: return .bool;
+    case .i8: return .i8;
+    case .i16: return .i16;
+    case .i32: return .i32;
+    case .i64: return .i64;
+    case .double: return .double;
+    case .binary: return .string;
+    case .list: return .list;
+    case .set: return .set;
+    case .map: return .map;
+    case .struct: return .struct;
+    }
+  }
+  
+  func compactType(_ ttype: TType) -> TCType {
+    switch ttype {
+    case .stop:   return .stop
+    case .void:   return .i8
+    case .bool:   return .boolean_FALSE
+    case .i8:   return .i8
+    case .double: return .double
+    case .i16:    return .i16
+    case .i32:    return .i32
+    case .i64:    return .i64
+    case .string: return .binary
+    case .struct: return .struct
+    case .map:    return .map
+    case .set:    return .set
+    case .list:   return .list
+    case .utf8:   return .binary
+    case .utf16:  return .binary
+    }
+  }
+  
+  /// ZigZag encoding maps signed integers to unsigned integers so that
+  /// numbers with a small absolute value (for instance, -1) have
+  /// a small varint encoded value too. It does this in a way that
+  /// "zig-zags" back and forth through the positive and negative integers,
+  /// so that -1 is encoded as 1, 1 is encoded as 2, -2 is encoded as 3, and so
+  ///
+  /// - parameter n: number to zigzag
+  ///
+  /// - returns: zigzaged UInt32
+  func i32ToZigZag(_ n : Int32) -> UInt32 {
+    return UInt32(n << 1) ^ UInt32(n >> 31)
+  }
+
+  func i64ToZigZag(_ n : Int64) -> UInt64 {
+    return UInt64(n << 1) ^ UInt64(n >> 63)
+  }
+
+  func zigZagToi32(_ n: UInt32) -> Int32 {
+    return Int32(n >> 1) ^ (-Int32(n & 1))
+  }
+  
+  func zigZagToi64(_ n: UInt64) -> Int64 {
+    return Int64(n >> 1) ^ (-Int64(n & 1))
+  }
+  
+  
+  
+  /// Mark: - TProtocol  
+  
+  public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+    let protocolId: UInt8 = try read()
+    
+    if protocolId != TCompactProtocol.protocolID {
+      let expected = String(format:"%2X", TCompactProtocol.protocolID)
+      let got      = String(format:"%2X", protocolId)
+      throw TProtocolError(message: "Wrong Protocol ID \(got)",
+                           extendedError: .mismatchedProtocol(expected: expected, got: got))
+
+    }
+
+    let versionAndType: UInt8 = try read()
+    let version: UInt8 = versionAndType & TCompactProtocol.versionMask
+    if version != TCompactProtocol.version {
+      throw TProtocolError(error: .badVersion(expected: "\(TCompactProtocol.version)",
+                                              got:"\(version)"))
+
+    }
+    
+    let type = (versionAndType >> UInt8(TCType.typeShiftAmount)) & TCType.typeBits
+    guard let mtype = TMessageType(rawValue: Int32(type)) else {
+      throw TProtocolError(message: "Unknown TMessageType value: \(type)")
+    }
+    let sequenceId = try readVarint32()
+    let name: String = try read()
+    
+    return (name, mtype, Int32(sequenceId))
+  }
+  
+  public func readMessageEnd() throws { }
+  
+  public func readStructBegin() throws -> String {
+    lastField.append(lastFieldId)
+    lastFieldId = 0
+    return ""
+  }
+  
+  public func readStructEnd() throws {
+    lastFieldId = lastField.last ?? 0
+    lastField.removeLast()
+  }
+  
+  public func readFieldBegin() throws -> (String, TType, Int32) {
+    let byte: UInt8 = try read()
+    guard let type = TCType(rawValue: byte & 0x0F) else {
+      throw TProtocolError(message: "Unknown TCType \(byte & 0x0F)")
+    }
+    
+    // if it's a stop, then we can return immediately, as the struct is over
+    if type == .stop {
+      return ("", .stop, 0)
+    }
+    
+    var fieldId: Int16 = 0
+    
+    // mask off the 4MSB of the type header.  it could contain a field id delta
+    let modifier = (byte & 0xF0) >> 4
+    if modifier == 0 {
+      // not a delta.  look ahead for the zigzag varint field id
+      fieldId = try read()
+    } else {
+      // has a delta.  add the delta to the last Read field id.
+      fieldId = Int16(lastFieldId + modifier)
+    }
+    
+    let fieldType = try ttype(type.rawValue)
+    
+    // if this happens to be a boolean field, the value is encoded in the type
+    if type == .boolean_TRUE || type == .boolean_FALSE {
+      // save the boolean value in a special instance variable
+      booleanValue = type == .boolean_TRUE
+    }
+    
+    // push the new field onto the field stack so we can keep the deltas going
+    lastFieldId = UInt8(fieldId)
+    return ("", fieldType, Int32(fieldId))
+  }
+  
+  public func readFieldEnd() throws { }
+  
+  public func read() throws -> String {
+    let length = try readVarint32()
+    
+    var result: String
+    
+    if length != 0 {
+      let data = try readBinary(Int(length))
+      result = String(data: data, encoding: String.Encoding.utf8) ?? ""
+    } else {
+      result = ""
+    }
+    
+    return result
+  }
+  
+  public func read() throws -> Bool {
+    if let val = booleanValue {
+      self.booleanValue = nil
+      return val
+    } else {
+      let result = try read() as UInt8
+      return TCType(rawValue: result) == .boolean_TRUE
+    }
+  }
+  
+  public func read() throws -> UInt8 {
+    var buff: UInt8 = 0
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 1)[0]
+    }
+    return buff
+  }
+  
+  public func read() throws -> Int16 {
+    let v = try readVarint32()
+    return Int16(zigZagToi32(v))
+  }
+  
+  public func read() throws -> Int32 {
+    let v = try readVarint32()
+    return zigZagToi32(v)
+  }
+  
+  public func read() throws -> Int64 {
+    let v = try readVarint64()
+    return zigZagToi64(v)
+  }
+  
+  public func read() throws -> Double {
+    var buff = Data()
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) {
+      buff = try self.transport.readAll(size: 8)
+    }
+    
+    let i64: UInt64 = buff.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) -> UInt64 in
+      return UnsafePointer<UInt64>(OpaquePointer(ptr)).pointee
+    }
+    let bits = CFSwapInt64LittleToHost(i64)
+    return unsafeBitCast(bits, to: Double.self)
+  }
+  
+  public func read() throws -> Data {
+    let length = try readVarint32()
+    return try readBinary(Int(length))
+  }
+  
+  public func readMapBegin() throws -> (TType, TType, Int32) {
+    var keyAndValueType: UInt8 = 8
+    let size = try readVarint32()
+    if size != 0 {
+      keyAndValueType = try read()
+    }
+    
+    let keyType = try ttype(keyAndValueType >> 4)
+    let valueType = try ttype(keyAndValueType & 0xF)
+    
+    return (keyType, valueType, Int32(size))
+  }
+  
+  public func readMapEnd() throws { }
+  
+  public func readSetBegin() throws -> (TType, Int32) {
+    return try readListBegin()
+  }
+  
+  public func readSetEnd() throws { }
+  
+  public func readListBegin() throws -> (TType, Int32) {
+    let sizeAndType: UInt8 = try read()
+    var size: UInt32 = UInt32(sizeAndType >> 4) & 0x0f
+    if size == 15 {
+      size = try readVarint32()
+    }
+    let elementType = try ttype(sizeAndType & 0x0F)
+    
+    return (elementType, Int32(size))
+  }
+  
+  public func readListEnd() throws { }
+  
+  public func writeMessageBegin(name: String,
+                                type messageType: TMessageType,
+                                sequenceID: Int32) throws {
+    try writebyteDirect(TCompactProtocol.protocolID)
+    let nextByte: UInt8 = (TCompactProtocol.version & TCompactProtocol.versionMask) |
+                          (UInt8((UInt32(messageType.rawValue) << UInt32(TCType.typeShiftAmount))) &
+                          TCType.typeMask)
+    try writebyteDirect(nextByte)
+    try writeVarint32(UInt32(sequenceID))
+    try write(name)
+    
+    currentMessageName = name
+  }
+  
+  public func writeMessageEnd() throws {
+    currentMessageName = nil
+  }
+  
+  public func writeStructBegin(name: String) throws {
+    lastField.append(lastFieldId)
+    lastFieldId = 0
+  }
+  
+  public func writeStructEnd() throws {
+    lastFieldId = lastField.last ?? 0
+    lastField.removeLast()
+  }
+  
+  public func writeFieldBegin(name: String,
+                              type fieldType: TType,
+                              fieldID: Int32) throws {
+    if fieldType == .bool {
+      boolFieldName = name
+      boolFieldType = fieldType
+      boolFieldId = fieldID
+      return
+    } else {
+      try writeFieldBeginInternal(name: name,
+                                  type: fieldType,
+                                  fieldID: fieldID,
+                                  typeOverride: 0xFF)
+    }
+  }
+  
+  func writeFieldBeginInternal(name: String,
+                               type fieldType: TType,
+                               fieldID: Int32,
+                               typeOverride: UInt8) throws {
+    
+    let typeToWrite = typeOverride == 0xFF ? compactType(fieldType).rawValue : typeOverride
+    
+    // check if we can use delta encoding for the field id
+    let diff = UInt8(fieldID) - lastFieldId
+    if (UInt8(fieldID) > lastFieldId) && (diff <= 15) {
+      // Write them together
+      try writebyteDirect((UInt8(fieldID) - lastFieldId) << 4 | typeToWrite)
+      
+    } else {
+      // Write them separate
+      try writebyteDirect(typeToWrite)
+      try write(Int16(fieldID))
+    }
+    
+    lastFieldId = UInt8(fieldID)
+      
+  }
+  
+  public func writeFieldStop() throws {
+    try writebyteDirect(TCType.stop.rawValue)
+  }
+  
+  public func writeFieldEnd() throws { }
+  
+  public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+    if size == 0 {
+      try writebyteDirect(0)
+    } else {
+      try writeVarint32(UInt32(size))
+      
+      let compactedTypes = compactType(keyType).rawValue << 4 | compactType(valueType).rawValue
+      try writebyteDirect(compactedTypes)
+    }
+  }
+  
+  public func writeMapEnd() throws { }
+  
+  public func writeSetBegin(elementType: TType, size: Int32) throws {
+    try writeCollectionBegin(elementType, size: size)
+  }
+  
+  public func writeSetEnd() throws { }
+  
+  public func writeListBegin(elementType: TType, size: Int32) throws {
+    try writeCollectionBegin(elementType, size: size)
+  }
+  
+  public func writeListEnd() throws { }
+  
+  public func write(_ value: String) throws {
+    try write(value.data(using: String.Encoding.utf8)!)
+  }
+  
+  public func write(_ value: Bool) throws {
+    if let boolFieldId = boolFieldId, let boolFieldType = boolFieldType,
+       let boolFieldName = boolFieldName {
+      
+      // we haven't written the field header yet
+      let compactType: TCType = value ? .boolean_TRUE : .boolean_FALSE
+      try writeFieldBeginInternal(name: boolFieldName, type: boolFieldType, fieldID: boolFieldId,
+                                  typeOverride: compactType.rawValue)
+      self.boolFieldId = nil
+      self.boolFieldType = nil
+      self.boolFieldName = nil
+    } else {
+      // we're not part of a field, so just write the value.
+      try writebyteDirect(value ? TCType.boolean_TRUE.rawValue : TCType.boolean_FALSE.rawValue)
+    }
+  }
+
+  public func write(_ value: UInt8) throws {
+    try writebyteDirect(value)
+  }
+
+  public func write(_ value: Int16) throws {
+    try writeVarint32(i32ToZigZag(Int32(value)))
+  }
+  
+  public func write(_ value: Int32) throws {
+    try writeVarint32(i32ToZigZag(value))
+  }
+  
+  public func write(_ value: Int64) throws {
+    try writeVarint64(i64ToZigZag(value))
+  }
+  
+  public func write(_ value: Double) throws {
+    var bits = CFSwapInt64HostToLittle(unsafeBitCast(value, to: UInt64.self))
+    let data = withUnsafePointer(to: &bits) {
+      return Data(bytes: UnsafePointer<UInt8>(OpaquePointer($0)), count: MemoryLayout<UInt64>.size)
+    }
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+      try self.transport.write(data: data)
+    }
+  }
+  
+  public func write(_ data: Data) throws {
+    try writeVarint32(UInt32(data.count))
+    try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) {
+      try self.transport.write(data: data)
+    }
+  }
+}
diff --git a/lib/swift/Sources/TEnum.swift b/lib/swift/Sources/TEnum.swift
new file mode 100644
index 0000000..fedfdb1
--- /dev/null
+++ b/lib/swift/Sources/TEnum.swift
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+public protocol TEnum : TSerializable, Hashable {
+  var rawValue: Int32 { get }
+}
+
+extension TEnum {
+  public static var thriftType: TType { return .i32 }
+  public var hashValue: Int { return rawValue.hashValue }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(rawValue)
+  }
+}
diff --git a/lib/swift/Sources/TError.swift b/lib/swift/Sources/TError.swift
new file mode 100644
index 0000000..79edba6
--- /dev/null
+++ b/lib/swift/Sources/TError.swift
@@ -0,0 +1,77 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+/// TErrorCode
+///
+/// Protocol for TError conformers' enum's to conform to.
+/// Generic Int Thrift error code to allow error cases to have
+/// associated values.
+public protocol TErrorCode : CustomStringConvertible {
+  var thriftErrorCode: Int { get }
+}
+
+/// TError
+///
+/// Base protocol for all Thrift Error(Exception) types to conform to
+public protocol TError : Error, CustomStringConvertible {
+
+  /// Enum for error cases.  Can be typealiased to any conforming enum
+  /// or defined nested.
+  associatedtype Code: TErrorCode
+  
+  /// Error Case, value from internal enum
+  var error: Code { get set }
+  
+  /// Optional additional message
+  var message: String? { get set }
+  
+  /// Default error case for the error type, used for generic init()
+  static var defaultCase: Code { get }
+  
+  init()
+}
+
+extension TError {
+  /// Human readable description of error. Default provided for you in the
+  /// format \(Self.self): \(error.errorDescription) \n message
+  /// eg:
+  ///
+  ///     TApplicationError (1): Invalid Message Type
+  ///     An unknown Error has occured.
+  public var description: String {
+    var out = "\(Self.self) (\(error.thriftErrorCode)): " + error.description + "\n"
+    if let message = message {
+      out += "Message: \(message)"
+    }
+    return out
+  }
+
+  /// Simple default Initializer for TError's
+  ///
+  /// - parameter error:   ErrorCode value.  Default: defaultCase
+  /// - parameter message: Custom message with error.  Optional
+  ///
+  /// - returns: <#return value description#>
+  public init(error: Code, message: String? = nil) {
+    self.init()
+    self.error = error
+    self.message = message
+  }
+}
diff --git a/lib/swift/Sources/TFileHandleTransport.swift b/lib/swift/Sources/TFileHandleTransport.swift
new file mode 100644
index 0000000..f315fef
--- /dev/null
+++ b/lib/swift/Sources/TFileHandleTransport.swift
@@ -0,0 +1,56 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+public class TFileHandleTransport: TTransport {
+  var inputFileHandle: FileHandle
+  var outputFileHandle: FileHandle
+  
+  public init(inputFileHandle: FileHandle, outputFileHandle: FileHandle) {
+    self.inputFileHandle = inputFileHandle
+    self.outputFileHandle = outputFileHandle
+  }
+  
+  public convenience init(fileHandle: FileHandle) {
+    self.init(inputFileHandle: fileHandle, outputFileHandle: fileHandle)
+  }
+  
+  public func read(size: Int) throws -> Data {
+    var data = Data()
+    while data.count < size {
+      let read = inputFileHandle.readData(ofLength: size - data.count)
+      data.append(read)
+      if read.count == 0 {
+        break
+      }
+    }
+    return data
+  }
+  
+  public func write(data: Data) throws {
+    outputFileHandle.write(data)
+  }
+  
+  public func flush() throws {
+    return
+  }
+}
+
+
diff --git a/lib/swift/Sources/TFileTransport.swift b/lib/swift/Sources/TFileTransport.swift
new file mode 100644
index 0000000..fe2253d
--- /dev/null
+++ b/lib/swift/Sources/TFileTransport.swift
@@ -0,0 +1,101 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+  import Darwin
+#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
+  import Glibc
+#endif
+
+/// TFileTransport
+/// Foundation-less Swift File transport.
+/// Uses C fopen/fread/fwrite,
+/// provided by Glibc in linux and Darwin on OSX/iOS
+public class TFileTransport: TTransport {
+  var fileHandle: UnsafeMutablePointer<FILE>? = nil
+  
+  public init (fileHandle: UnsafeMutablePointer<FILE>) {
+    self.fileHandle = fileHandle
+  }
+
+  public convenience init(filename: String) throws {
+    var fileHandle: UnsafeMutablePointer<FILE>?
+    filename.withCString({ cFilename in
+      "rw".withCString({ cMode in
+        fileHandle = fopen(cFilename, cMode)
+      })
+    })
+    if let fileHandle = fileHandle {
+      self.init(fileHandle: fileHandle)
+    } else {
+      throw TTransportError(error: .notOpen)
+    }
+  }
+  
+  deinit {
+    fclose(self.fileHandle)
+  }
+  
+  public func readAll(size: Int) throws -> Data {
+    let read = try self.read(size: size)
+    
+    if read.count != size {
+      throw TTransportError(error: .endOfFile)
+    }
+    return read
+  }
+  
+  public func read(size: Int) throws -> Data {
+    // set up read buffer, position 0
+    var read = Data(capacity: size)
+    var position = 0
+    
+    // read character buffer
+    var nextChar: UInt8 = 0
+    
+    // continue until we've read size bytes
+    while read.count < size {
+      if fread(&nextChar, 1, 1, self.fileHandle) == 1 {
+        read[position] = nextChar
+
+        // Increment output byte pointer
+        position += 1
+        
+      } else {
+        throw TTransportError(error: .endOfFile)
+      }
+    }
+    return read
+  }
+  
+  public func write(data: Data) throws {
+    let bytesWritten = data.withUnsafeBytes {
+      fwrite($0, 1, data.count, self.fileHandle)
+    }
+    if bytesWritten != data.count {
+      throw TTransportError(error: .unknown)
+    }
+  }
+  
+  public func flush() throws {
+    return
+  }
+}
diff --git a/lib/swift/Sources/TFramedTransport.swift b/lib/swift/Sources/TFramedTransport.swift
new file mode 100644
index 0000000..ca385d6
--- /dev/null
+++ b/lib/swift/Sources/TFramedTransport.swift
@@ -0,0 +1,123 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+public class TFramedTransport: TTransport {
+  public static let headerSize    = 4
+  public static let initFrameSize = 1024
+  private static let defaultMaxLength = 16384000
+
+  public var transport: TTransport
+  private var writeBuffer = Data()
+
+  private var maxSize     = TFramedTransport.defaultMaxLength
+  private var remainingBytes = 0
+
+
+  public init(transport: TTransport, maxSize: Int) {
+    self.transport = transport
+    self.maxSize = maxSize
+  }
+
+  public convenience init(transport: TTransport) {
+    self.init(transport: transport, maxSize: TFramedTransport.defaultMaxLength)
+  }
+
+  func readHeader() throws {
+    let read = try transport.readAll(size: TFramedTransport.headerSize)
+    remainingBytes = Int(decodeFrameSize(data: read))
+  }
+
+  /// Mark: - TTransport
+
+  public func read(size: Int) throws -> Data {
+    while (remainingBytes <= 0) {
+        try readHeader()
+    }
+
+    let toRead = min(size, remainingBytes)
+
+    if toRead < 0 {
+        try close()
+        throw TTransportError(error: .negativeSize,
+                              message:  "Read a negative frame size (\(toRead))!")
+    }
+
+    if toRead > maxSize {
+        try close()
+        throw TTransportError(error: .sizeLimit(limit: maxSize, got: toRead))
+    }
+
+    return try transport.readAll(size: toRead)
+  }
+
+  public func flush() throws {
+    // copy buffer and reset
+    let buff = writeBuffer
+    writeBuffer = Data()
+
+    if buff.count - TFramedTransport.headerSize < 0 {
+      throw TTransportError(error: .unknown)
+    }
+
+    let frameSize = encodeFrameSize(size: UInt32(buff.count))
+
+    try transport.write(data: frameSize)
+    try transport.write(data: buff)
+    try transport.flush()
+  }
+
+  public func write(data: Data) throws {
+    writeBuffer.append(data)
+  }
+
+
+
+  private func encodeFrameSize(size: UInt32) -> Data {
+    var data = Data()
+    data.append(Data(bytes: [UInt8(0xff & (size >> 24))]))
+    data.append(Data(bytes: [UInt8(0xff & (size >> 16))]))
+    data.append(Data(bytes: [UInt8(0xff & (size >> 8))]))
+    data.append(Data(bytes: [UInt8(0xff & (size))]))
+
+    return data
+  }
+
+  private func decodeFrameSize(data: Data) -> UInt32 {
+    var size: UInt32
+    size  = (UInt32(data[0] & 0xff) << 24)
+    size |= (UInt32(data[1] & 0xff) << 16)
+    size |= (UInt32(data[2] & 0xff) <<  8)
+    size |= (UInt32(data[3] & 0xff))
+    return size
+  }
+
+  public func close() throws {
+    try transport.close()
+  }
+
+  public func open() throws {
+    try transport.open()
+  }
+
+  public func isOpen() throws -> Bool {
+    return try transport.isOpen()
+  }
+}
diff --git a/lib/swift/Sources/THTTPSessionTransport.swift b/lib/swift/Sources/THTTPSessionTransport.swift
new file mode 100644
index 0000000..3c0af8e
--- /dev/null
+++ b/lib/swift/Sources/THTTPSessionTransport.swift
@@ -0,0 +1,184 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+import Dispatch
+
+
+public class THTTPSessionTransport: TAsyncTransport {
+  public class Factory : TAsyncTransportFactory {
+    public var responseValidate: ((HTTPURLResponse?, Data?) throws -> Void)?
+    
+    var session: URLSession
+    var url: URL
+    
+    public class func setupDefaultsForSessionConfiguration(_ config: URLSessionConfiguration, withProtocolName protocolName: String?) {
+      var thriftContentType = "application/x-thrift"
+      
+      if let protocolName = protocolName {
+        thriftContentType += "; p=\(protocolName)"
+      }
+      
+      config.requestCachePolicy = .reloadIgnoringLocalCacheData
+      config.urlCache = nil
+      
+      config.httpShouldUsePipelining  = true
+      config.httpShouldSetCookies     = true
+      config.httpAdditionalHeaders    = ["Content-Type": thriftContentType,
+                                         "Accept": thriftContentType,
+                                         "User-Agent": "Thrift/Swift (Session)"]
+      
+      
+    }
+    
+    public init(session: URLSession, url: URL) {
+      self.session = session
+      self.url = url
+    }
+    
+    public func newTransport() -> THTTPSessionTransport {
+      return THTTPSessionTransport(factory: self)
+    }
+    
+    func validateResponse(_ response: HTTPURLResponse?, data: Data?) throws {
+      try responseValidate?(response, data)
+    }
+    
+    func taskWithRequest(_ request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> ()) throws -> URLSessionTask {
+      
+      let newTask: URLSessionTask? = session.dataTask(with: request, completionHandler: completionHandler)
+      if let newTask = newTask {
+        return newTask
+      } else {
+        throw TTransportError(error: .unknown, message: "Failed to create session data task")
+      }
+    }    
+  }
+  
+  var factory: Factory
+  var requestData = Data()
+  var responseData = Data()
+  var responseDataOffset: Int = 0
+  
+  init(factory: Factory) {
+    self.factory = factory
+  }
+  
+  public func readAll(size: Int) throws -> Data {
+    let read = try self.read(size: size)
+    if read.count != size {
+      throw TTransportError(error: .endOfFile)
+    }
+    return read
+  }
+  
+  public func read(size: Int) throws -> Data {
+    let avail = responseData.count - responseDataOffset
+    let (start, stop) = (responseDataOffset, responseDataOffset + min(size, avail))
+    let read = responseData.subdata(in: start..<stop)
+    responseDataOffset += read.count
+    return read
+  }
+  
+  public func write(data: Data) throws {
+    requestData.append(data)
+  }
+  
+  public func flush(_ completed: @escaping (TAsyncTransport, Error?) -> Void) {
+    var error: Error?
+    var task: URLSessionTask?
+    
+    var request = URLRequest(url: factory.url)
+    request.httpMethod = "POST"
+    request.httpBody =  requestData
+
+    requestData = Data()
+
+    do {
+      task = try factory.taskWithRequest(request, completionHandler: { (data, response, taskError) in
+
+        // Check if there was an error with the network
+        if taskError != nil {
+            error = TTransportError(error: .timedOut)
+            completed(self, error)
+            return
+        }
+
+        // Check response type
+        if taskError == nil && !(response is HTTPURLResponse) {
+            error = THTTPTransportError(error: .invalidResponse)
+            completed(self, error)
+            return
+        }
+        
+        // Check status code
+        if let httpResponse = response as? HTTPURLResponse {
+          if taskError == nil && httpResponse.statusCode != 200 {
+            if httpResponse.statusCode == 401 {
+              error = THTTPTransportError(error: .authentication)
+            } else {
+              error = THTTPTransportError(error: .invalidStatus(statusCode: httpResponse.statusCode))
+            }
+          }
+          
+          // Allow factory to check
+          if error != nil {
+            do {
+              try self.factory.validateResponse(httpResponse, data: data)
+            } catch let validateError {
+              error = validateError
+            }
+          }
+          
+          self.responseDataOffset = 0
+          if error != nil {
+            self.responseData = Data()
+          } else {
+            self.responseData = data ?? Data()
+          }
+          completed(self, error)
+        }
+      })
+      
+    } catch let taskError {
+      error = taskError
+    }
+    
+    if let error = error, task == nil {
+      completed(self, error)
+    }
+    task?.resume()
+  }
+
+  public func flush() throws {
+    let completed = DispatchSemaphore(value: 0)
+    var internalError: Error?
+    
+    flush() { _, error in
+      internalError = error
+      completed.signal()
+    }
+    
+    _ = completed.wait(timeout: DispatchTime.distantFuture)
+    
+    if let error = internalError {
+      throw error
+    }
+  }
+}
diff --git a/lib/swift/Sources/TList.swift b/lib/swift/Sources/TList.swift
new file mode 100644
index 0000000..0077156
--- /dev/null
+++ b/lib/swift/Sources/TList.swift
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+public struct TList<Element : TSerializable> : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable {
+  typealias Storage = Array<Element>
+  public typealias Indices = Storage.Indices
+
+  internal var storage = Storage()
+  public init() { }
+  public init(arrayLiteral elements: Element...) {
+    self.storage = Storage(elements)
+  }
+  public init<Source : Sequence>(_ sequence: Source) where Source.Iterator.Element == Element {
+    storage = Storage(sequence)
+  }
+
+  /// Mark: Hashable
+  public var hashValue : Int {
+    let prime = 31
+    var result = 1
+    for element in storage {
+      result = prime &* result &+ element.hashValue
+    }
+    return result
+  }
+  
+  /// Mark: TSerializable
+  public static var thriftType : TType { return .list }
+
+  public static func read(from proto: TProtocol) throws -> TList {
+    let (elementType, size) = try proto.readListBegin()
+    if elementType != Element.thriftType {
+      throw TProtocolError(error: .invalidData,
+                           extendedError: .unexpectedType(type: elementType))
+    }
+    var list = TList()
+    for _ in 0..<size {
+      let element = try Element.read(from: proto)
+      list.storage.append(element)
+    }
+    try proto.readListEnd()
+    return list
+  }
+  
+  public func write(to proto: TProtocol) throws {
+    try proto.writeListBegin(elementType: Element.thriftType, size: Int32(self.count))
+    for element in self.storage {
+      try Element.write(element, to: proto)
+    }
+    try proto.writeListEnd()
+  }
+
+  /// Mark: MutableCollection
+  
+  public typealias SubSequence = Storage.SubSequence
+  public typealias Index = Storage.Index
+  
+  public subscript(position: Storage.Index) -> Element {
+    get {
+      return storage[position]
+    }
+    set {
+      storage[position] = newValue
+    }
+  }
+  
+  public subscript(range: Range<Index>) -> SubSequence {
+    get {
+      return storage[range]
+    }
+    set {
+      storage[range] = newValue
+    }
+  }
+  
+  public var startIndex: Index {
+    return storage.startIndex
+  }
+  public var endIndex: Index {
+    return storage.endIndex
+  }
+  
+  public func formIndex(after i: inout Index) {
+    storage.formIndex(after: &i)
+  }
+  
+  public func formIndex(before i: inout Int) {
+    storage.formIndex(before: &i)
+  }
+  
+  public func index(after i: Index) -> Index {
+    return storage.index(after: i)
+  }
+
+  public func index(before i: Int) -> Int {
+    return storage.index(before: i)
+  }
+
+}
+
+extension TList : RangeReplaceableCollection {
+  public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C)
+    where C.Iterator.Element == Element {
+    storage.replaceSubrange(subrange, with: newElements)
+  }
+}
+
+extension TList : CustomStringConvertible, CustomDebugStringConvertible {
+  
+  public var description : String {
+    return storage.description
+  }
+  
+  public var debugDescription : String {
+    return storage.debugDescription
+  }
+  
+}
+
+public func ==<Element>(lhs: TList<Element>, rhs: TList<Element>) -> Bool {
+  return lhs.storage.elementsEqual(rhs.storage) { $0 == $1 }
+}
diff --git a/lib/swift/Sources/TMap.swift b/lib/swift/Sources/TMap.swift
new file mode 100644
index 0000000..f8b02d2
--- /dev/null
+++ b/lib/swift/Sources/TMap.swift
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+public struct TMap<Key : TSerializable & Hashable, Value : TSerializable>: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable {
+  typealias Storage = Dictionary<Key, Value>
+  public typealias Element = Storage.Element
+  public typealias Index = Storage.Index
+  public typealias IndexDistance = Storage.IndexDistance
+  public typealias Indices = Storage.Indices
+  public typealias SubSequence = Storage.SubSequence
+  internal var storage = Storage()
+  
+  /// Mark: Be Like Dictionary
+  
+  public func indexForKey(_ key: Key) -> Index? {
+    return storage.index(forKey: key)
+  }
+  
+  public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
+    return updateValue(value, forKey: key)
+  }
+  
+  public mutating func removeAtIndex(_ index: DictionaryIndex<Key, Value>) -> (Key, Value) {
+    return removeAtIndex(index)
+  }
+  
+  public mutating func removeValueForKey(_ key: Key) -> Value? {
+    return storage.removeValue(forKey: key)
+  }
+  
+  public init(minimumCapacity: Int) {
+    storage = Storage(minimumCapacity: minimumCapacity)
+  }
+  
+  /// init from Dictionary<K,V>
+  public init(_ dict: [Key: Value]) {
+    storage = dict
+  }
+
+  /// read only access to storage if needed as Dictionary<K,V>
+  public var dictionary: [Key: Value] {
+    return storage
+  }
+  
+  public subscript (key: Key) -> Value? {
+    get {
+      return storage[key]
+    }
+    set {
+      storage[key] = newValue
+    }
+  }
+  
+  /// Mark: Collection
+  
+  public var indices: Indices {
+    return storage.indices
+  }
+  
+  public func distance(from start: Index, to end: Index) -> IndexDistance {
+    return storage.distance(from: start, to: end)
+  }
+  
+  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+    return storage.index(i, offsetBy: n)
+  }
+  
+  public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
+    return storage.index(i, offsetBy: n, limitedBy: limit)
+  }
+  
+  public subscript(position: Index) -> Element {
+    return storage[position]
+  }
+  
+  /// Mark: IndexableBase
+  
+  public var startIndex: Index { return storage.startIndex }
+  public var endIndex: Index { return storage.endIndex }
+  public func index(after i: Index) -> Index {
+    return storage.index(after: i)
+  }
+  
+  public func formIndex(after i: inout Index) {
+    storage.formIndex(after: &i)
+  }
+  
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    return storage[bounds]
+  }
+  
+  /// Mark: DictionaryLiteralConvertible
+  
+  public init(dictionaryLiteral elements: (Key, Value)...) {
+    storage = Storage()
+    for (key, value) in elements {
+      storage[key] = value
+    }
+  }
+
+  /// Mark: Hashable
+  
+  public var hashValue: Int {
+    let prime = 31
+    var result = 1
+    for (key, value) in storage {
+      result = prime &* result &+ key.hashValue
+      result = prime &* result &+ value.hashValue
+    }
+    return result
+  }
+  
+  /// Mark: TSerializable
+  
+  public static var thriftType : TType { return .map }
+  public init() {
+    storage = Storage()
+  }
+   
+  public static func read(from proto: TProtocol) throws -> TMap {
+
+    let (keyType, valueType, size) = try proto.readMapBegin()
+    if size > 0 {
+      if keyType != Key.thriftType {
+        throw TProtocolError(error: .invalidData,
+                             message: "Unexpected TMap Key Type",
+                             extendedError: .unexpectedType(type: keyType))
+      }
+      if valueType != Value.thriftType {
+        throw TProtocolError(error: .invalidData,
+                             message: "Unexpected TMap Value Type",
+                             extendedError: .unexpectedType(type: valueType))
+      }
+    }
+
+    var map = TMap()
+    for _ in 0..<size {
+      let key = try Key.read(from: proto)
+      let value = try Value.read(from: proto)
+      map.storage[key] = value
+    }
+    try proto.readMapEnd()
+    return map
+  }
+  
+  public func write(to proto: TProtocol) throws {
+    try proto.writeMapBegin(keyType: Key.thriftType,
+                            valueType: Value.thriftType, size: Int32(self.count))
+    for (key, value) in self.storage {
+      try Key.write(key, to: proto)
+      try Value.write(value, to: proto)
+    }
+    try proto.writeMapEnd()
+  }
+}
+
+/// Mark: CustomStringConvertible, CustomDebugStringConvertible
+
+extension TMap : CustomStringConvertible, CustomDebugStringConvertible {
+  
+  public var description : String {
+    return storage.description
+  }
+  
+  public var debugDescription : String {
+    return storage.debugDescription
+  }
+  
+}
+
+/// Mark: Equatable
+
+public func ==<Key, Value>(lhs: TMap<Key,Value>, rhs: TMap<Key, Value>) -> Bool {
+  if lhs.count != rhs.count {
+    return false
+  }
+  return lhs.storage.elementsEqual(rhs.storage) { $0.key == $1.key && $0.value == $1.value }
+}
diff --git a/lib/swift/Sources/TMemoryBufferTransport.swift b/lib/swift/Sources/TMemoryBufferTransport.swift
new file mode 100644
index 0000000..bd58b6e
--- /dev/null
+++ b/lib/swift/Sources/TMemoryBufferTransport.swift
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+public class TMemoryBufferTransport : TTransport {
+  public private(set) var readBuffer = Data()
+  public private(set) var writeBuffer = Data()
+  
+  public private(set) var position = 0
+
+  public var bytesRemainingInBuffer: Int {
+    return readBuffer.count - position
+  }
+  
+  public func consumeBuffer(size: Int) {
+    position += size
+  }
+  public func clear() {
+    readBuffer = Data()
+    writeBuffer = Data()
+  }
+  
+  
+  private var flushHandler: ((TMemoryBufferTransport, Data) -> ())?
+  
+  public init(flushHandler: ((TMemoryBufferTransport, Data) -> ())? = nil) {
+    self.flushHandler = flushHandler
+  }
+  
+  public convenience init(readBuffer: Data, flushHandler: ((TMemoryBufferTransport, Data) -> ())? = nil) {
+    self.init()
+    self.readBuffer = readBuffer
+  }
+  
+  public func reset(readBuffer: Data = Data(), writeBuffer: Data = Data()) {
+    self.readBuffer = readBuffer
+    self.writeBuffer = writeBuffer
+  }
+  
+  public func read(size: Int) throws -> Data {
+    let amountToRead = min(bytesRemainingInBuffer, size)
+    if amountToRead > 0 {
+      let ret = readBuffer.subdata(in: Range(uncheckedBounds: (lower: position, upper: position + amountToRead)))
+      position += ret.count
+      return ret
+    }
+    return Data()
+  }
+  
+  public func write(data: Data) throws {
+    writeBuffer.append(data)
+  }
+  
+  public func flush() throws {
+    flushHandler?(self, writeBuffer)
+  }
+}
diff --git a/lib/swift/Sources/TMultiplexedProtocol.swift b/lib/swift/Sources/TMultiplexedProtocol.swift
new file mode 100644
index 0000000..73a8d51
--- /dev/null
+++ b/lib/swift/Sources/TMultiplexedProtocol.swift
@@ -0,0 +1,47 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+public class TMultiplexedProtocol<Protocol: TProtocol>: TWrappedProtocol<Protocol> {
+  public let separator = ":"
+
+  public var serviceName = ""
+  
+  public convenience init(on transport: TTransport, serviceName: String) {
+    self.init(on: transport)
+    self.serviceName = serviceName    
+  }
+
+  override public func writeMessageBegin(name: String,
+                                         type messageType: TMessageType,
+                                         sequenceID: Int32) throws {
+    switch messageType {
+    case .call, .oneway:
+      var serviceFunction = serviceName
+      serviceFunction += serviceName == "" ? "" : separator
+      serviceFunction += name
+      return try super.writeMessageBegin(name: serviceFunction,
+                                         type: messageType,
+                                         sequenceID: sequenceID)
+    default:
+      return try super.writeMessageBegin(name: name,
+                                         type: messageType,
+                                         sequenceID: sequenceID)
+    }
+  }
+}
diff --git a/lib/swift/Sources/TProcessor.swift b/lib/swift/Sources/TProcessor.swift
new file mode 100644
index 0000000..7ff222e
--- /dev/null
+++ b/lib/swift/Sources/TProcessor.swift
@@ -0,0 +1,29 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+
+public typealias TProcessorMessageHandler<T> = (Int, TProtocol, TProtocol, T) -> Void
+
+public protocol TProcessor {
+  associatedtype Service
+  var service: Service { get set }
+  func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws
+  init(service: Service)
+}
+
diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift
new file mode 100644
index 0000000..a4e4a20
--- /dev/null
+++ b/lib/swift/Sources/TProtocol.swift
@@ -0,0 +1,182 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+//
+
+public enum TMessageType: Int32 {
+  case call = 1
+  case reply = 2
+  case exception = 3
+  case oneway = 4
+}
+
+public enum TType: Int32 {
+  case stop     = 0
+  case void     = 1
+  case bool     = 2
+  case i8       = 3
+  case double   = 4
+  case i16      = 6
+  case i32      = 8
+  case i64      = 10
+  case string   = 11
+  case `struct` = 12
+  case map      = 13
+  case set      = 14
+  case list     = 15
+  case utf8     = 16
+  case utf16    = 17
+}
+
+public protocol TProtocol {
+  var transport: TTransport { get set }
+  init(on transport: TTransport)
+  // Reading Methods
+  
+  func readMessageBegin() throws -> (String, TMessageType, Int32)
+  func readMessageEnd() throws
+  func readStructBegin() throws -> String
+  func readStructEnd() throws
+  func readFieldBegin() throws -> (String, TType, Int32)
+  func readFieldEnd() throws
+  func readMapBegin() throws -> (TType, TType, Int32)
+  func readMapEnd() throws
+  func readSetBegin() throws -> (TType, Int32)
+  func readSetEnd() throws
+  func readListBegin() throws -> (TType, Int32)
+  func readListEnd() throws
+  
+  func read() throws -> String
+  func read() throws -> Bool
+  func read() throws -> UInt8
+  func read() throws -> Int16
+  func read() throws -> Int32
+  func read() throws -> Int64
+  func read() throws -> Double
+  func read() throws -> Data
+  
+  // Writing methods
+  
+  func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws
+  func writeMessageEnd() throws
+  func writeStructBegin(name: String) throws
+  func writeStructEnd() throws
+  func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws
+  func writeFieldStop() throws
+  func writeFieldEnd() throws
+  func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws
+  func writeMapEnd() throws
+  func writeSetBegin(elementType: TType, size: Int32) throws
+  func writeSetEnd() throws
+  func writeListBegin(elementType: TType, size: Int32) throws
+  func writeListEnd() throws
+
+  func write(_ value: String) throws
+  func write(_ value: Bool) throws
+  func write(_ value: UInt8) throws
+  func write(_ value: Int16) throws
+  func write(_ value: Int32) throws
+  func write(_ value: Int64) throws
+  func write(_ value: Double) throws
+  func write(_ value: Data) throws
+}
+
+public extension TProtocol {
+  public func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
+    try writeFieldBegin(name: name, type: type, fieldID: id)
+    try value.write(to: self)
+    try writeFieldEnd()
+  }
+
+  public func validateValue(_ value: Any?, named name: String) throws {
+    if value == nil {
+      throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)")
+    }
+  }
+  
+  public func readResultMessageBegin() throws {
+    let (_, type, _) = try readMessageBegin();
+    if type == .exception {
+      let x = try readException()
+      throw x
+    }
+    return
+  }
+  
+  public func readException() throws -> TApplicationError {
+    return try TApplicationError.read(from: self)
+  }
+  
+  public func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
+    try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID)
+    try ex.write(to: self)
+    try writeMessageEnd()
+  }
+  
+  public func skip(type: TType) throws {
+    switch type {
+    case .bool:   _ = try read() as Bool
+    case .i8:   _ = try read() as UInt8
+    case .i16:    _ = try read() as Int16
+    case .i32:    _ = try read() as Int32
+    case .i64:    _ = try read() as Int64
+    case .double: _ = try read() as Double
+    case .string: _ = try read() as String
+      
+    case .struct:
+      _ = try readStructBegin()
+      while true {
+        let (_, fieldType, _) = try readFieldBegin()
+        if fieldType == .stop {
+          break
+        }
+        try skip(type: fieldType)
+        try readFieldEnd()
+      }
+      try readStructEnd()
+      
+      
+    case .map:
+      let (keyType, valueType, size) = try readMapBegin()
+      for _ in 0..<size {
+        try skip(type: keyType)
+        try skip(type: valueType)
+      }
+      try readMapEnd()
+      
+      
+    case .set:
+      let (elemType, size) = try readSetBegin()
+      for _ in 0..<size {
+        try skip(type: elemType)
+      }
+      try readSetEnd()
+      
+    case .list:
+      let (elemType, size) = try readListBegin()
+      for _ in 0..<size {
+        try skip(type: elemType)
+      }
+      try readListEnd()
+    default:
+      return
+    }
+  }
+}
diff --git a/lib/swift/Sources/TProtocolError.swift b/lib/swift/Sources/TProtocolError.swift
new file mode 100644
index 0000000..a5d14f9
--- /dev/null
+++ b/lib/swift/Sources/TProtocolError.swift
@@ -0,0 +1,146 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+public struct TProtocolError : TError {
+  public init() { }
+
+  public enum Code : TErrorCode {
+    case unknown
+    case invalidData
+    case negativeSize
+    case sizeLimit(limit: Int, got: Int)
+    case badVersion(expected: String, got: String)
+    case notImplemented
+    case depthLimit
+
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:        return 0
+      case .invalidData:    return 1
+      case .negativeSize:   return 2
+      case .sizeLimit:      return 3
+      case .badVersion:     return 4
+      case .notImplemented: return 5
+      case .depthLimit:     return 6
+      }
+
+    }
+    public var description: String {
+      switch self {
+      case .unknown:        return "Unknown TProtocolError"
+      case .invalidData:    return "Invalid Data"
+      case .negativeSize:   return "Negative Size"
+      case .sizeLimit(let limit, let got):
+        return "Message exceeds size limit of \(limit) (received: \(got)"
+      case .badVersion(let expected, let got):
+        return "Bad Version. (Expected: \(expected), Got: \(got)"
+      case .notImplemented: return "Not Implemented"
+      case .depthLimit:     return "Depth Limit"
+      }
+    }
+  }
+
+  public enum ExtendedErrorCode : TErrorCode {
+    case unknown
+    case missingRequiredField(fieldName: String)
+    case unexpectedType(type: TType)
+    case mismatchedProtocol(expected: String, got: String)
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:              return 1000
+      case .missingRequiredField: return 1001
+      case .unexpectedType:       return 1002
+      case .mismatchedProtocol:   return 1003
+      }
+    }
+    public var description: String {
+      switch self {
+      case .unknown:                                    return "Unknown TProtocolExtendedError"
+      case .missingRequiredField(let fieldName):        return "Missing Required Field: \(fieldName)"
+      case .unexpectedType(let type):                   return "Unexpected Type \(type.self)"
+      case .mismatchedProtocol(let expected, let got):  return "Mismatched Protocol.  (Expected: \(expected), got \(got))"
+      }
+    }
+  }
+
+  public var extendedError: ExtendedErrorCode? = nil
+
+  public init(error: Code = .unknown,
+              message: String? = nil,
+              extendedError: ExtendedErrorCode? = nil) {
+    self.error = error
+    self.message = message
+    self.extendedError = extendedError
+  }
+
+  /// Mark: TError
+  public var error: Code = .unknown
+  public var message: String? = nil
+  public static var defaultCase: Code { return .unknown }
+
+  public var description: String {
+    var out = "\(TProtocolError.self):  (\(error.thriftErrorCode) \(error.description)\n"
+    if let extendedError = extendedError {
+      out += "TProtocolExtendedError (\(extendedError.thriftErrorCode)): \(extendedError.description)"
+    }
+    if let message = message {
+      out += "Message: \(message)"
+    }
+    return out
+  }
+}
+
+
+/// Wrapper for Transport errors in Protocols.  Inspired by Thrift-Cocoa PROTOCOL_TRANSPORT_ERROR
+/// macro.  Modified to be more Swift-y.  Catches any TError thrown within the block and
+/// rethrows a given TProtocolError, the original error's description is appended to the new
+/// TProtocolError's message.  sourceFile, sourceLine, sourceMethod are auto-populated and should
+/// be ignored when calling.
+///
+/// - parameter error:        TProtocolError to throw if the block throws
+/// - parameter sourceFile:   throwing file, autopopulated
+/// - parameter sourceLine:   throwing line, autopopulated
+/// - parameter sourceMethod: throwing method, autopopulated
+/// - parameter block:        throwing block
+///
+/// - throws: TProtocolError  Default is TProtocolError.ErrorCode.unknown.  Underlying
+///                           error's description appended to TProtocolError.message
+func ProtocolTransportTry(error: TProtocolError = TProtocolError(),
+                          sourceFile: String = #file,
+                          sourceLine: Int = #line,
+                          sourceMethod: String = #function,
+                          block: () throws -> ()) throws {
+  // Need mutable copy
+  var error = error
+  do {
+    try block()
+  } catch let err as TError {
+    var message = error.message ?? ""
+    message += "\nFile: \(sourceFile)\n"
+    message += "Line: \(sourceLine)\n"
+    message += "Method: \(sourceMethod)"
+    message += "\nOriginal Error:\n" + err.description
+    error.message = message
+    throw error
+  }
+}
+
+
diff --git a/lib/swift/Sources/TSSLSocketTransport.swift b/lib/swift/Sources/TSSLSocketTransport.swift
new file mode 100644
index 0000000..c2b5902
--- /dev/null
+++ b/lib/swift/Sources/TSSLSocketTransport.swift
@@ -0,0 +1,229 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+import CoreFoundation
+
+#if os(Linux)
+public class TSSLSocketTransport {
+  init(hostname: String, port: UInt16) {
+    // FIXME!
+    assert(false, "Security not available in Linux, TSSLSocketTransport Unavilable for now")
+  }
+}
+#else
+let isLittleEndian = Int(OSHostByteOrder()) == OSLittleEndian
+let htons  = isLittleEndian ? _OSSwapInt16 : { $0 }
+let htonl  = isLittleEndian ? _OSSwapInt32 : { $0 }
+
+public class TSSLSocketTransport: TStreamTransport {
+  var sslHostname: String
+  var sd: Int32 = 0
+  
+  public init(hostname: String, port: UInt16) throws {
+    sslHostname = hostname
+    var readStream: Unmanaged<CFReadStream>?
+    var writeStream: Unmanaged<CFWriteStream>?
+    
+    /* create a socket structure */
+    var pin: sockaddr_in = sockaddr_in()
+    var hp: UnsafeMutablePointer<hostent>? = nil
+    for i in 0..<10 {
+      
+      hp = gethostbyname(hostname.cString(using: String.Encoding.utf8)!)
+      if hp == nil {
+        print("failed to resolve hostname \(hostname)")
+        herror("resolv")
+        if i == 9 {
+          super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+          throw TSSLSocketTransportError(error: .hostanameResolution(hostname: hostname))
+        }
+        Thread.sleep(forTimeInterval: 0.2)
+      } else {
+        break
+      }
+    }
+    pin.sin_family  = UInt8(AF_INET)
+    pin.sin_addr    = in_addr(s_addr: UInt32((hp?.pointee.h_addr_list.pointee?.pointee)!)) // Is there a better way to get this???
+    pin.sin_port    = htons(port)
+    
+    /* create the socket */
+    sd = socket(Int32(AF_INET), Int32(SOCK_STREAM), Int32(IPPROTO_TCP))
+    if sd == -1 {
+      super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+      throw TSSLSocketTransportError(error: .socketCreate(port: Int(port)))
+    }
+    
+    /* open a connection */
+    // need a non-self ref to sd, otherwise the j complains
+    let sd_local = sd
+    let connectResult = withUnsafePointer(to: &pin) {
+      connect(sd_local, UnsafePointer<sockaddr>(OpaquePointer($0)), socklen_t(MemoryLayout<sockaddr_in>.size))
+    }
+    if connectResult == -1 {
+      super.init(inputStream: nil, outputStream: nil) // have to init before throwing
+      throw TSSLSocketTransportError(error: .connect)
+    }
+    
+    CFStreamCreatePairWithSocket(kCFAllocatorDefault, sd, &readStream, &writeStream)
+    
+    CFReadStreamSetProperty(readStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
+    CFWriteStreamSetProperty(writeStream?.takeRetainedValue(), .socketNativeHandle, kCFBooleanTrue)
+    
+    var inputStream: InputStream? = nil
+    var outputStream: OutputStream? = nil
+    if readStream != nil && writeStream != nil {
+      
+      CFReadStreamSetProperty(readStream?.takeRetainedValue(),
+                              .socketSecurityLevel,
+                              kCFStreamSocketSecurityLevelTLSv1)
+      
+      let settings: [String: Bool] = [kCFStreamSSLValidatesCertificateChain as String: true]
+      
+      CFReadStreamSetProperty(readStream?.takeRetainedValue(),
+                              .SSLSettings,
+                              settings as CFTypeRef!)
+      
+      CFWriteStreamSetProperty(writeStream?.takeRetainedValue(),
+                              .SSLSettings,
+                              settings as CFTypeRef!)
+      
+      inputStream = readStream!.takeRetainedValue()
+      inputStream?.schedule(in: .current, forMode: .defaultRunLoopMode)
+      inputStream?.open()
+      
+      outputStream = writeStream!.takeRetainedValue()
+      outputStream?.schedule(in: .current, forMode: .defaultRunLoopMode)
+      outputStream?.open()
+      
+      readStream?.release()
+      writeStream?.release()
+    }
+    
+    
+    super.init(inputStream: inputStream, outputStream: outputStream)
+    self.input?.delegate = self
+    self.output?.delegate = self
+  }
+  
+  func recoverFromTrustFailure(_ myTrust: SecTrust, lastTrustResult: SecTrustResultType) -> Bool {
+    let trustTime = SecTrustGetVerifyTime(myTrust)
+    let currentTime = CFAbsoluteTimeGetCurrent()
+    
+    let timeIncrement = 31536000 // from TSSLSocketTransport.m
+    let newTime = currentTime - Double(timeIncrement)
+    
+    if trustTime - newTime != 0 {
+      let newDate = CFDateCreate(nil, newTime)
+      SecTrustSetVerifyDate(myTrust, newDate!)
+      
+      var tr = lastTrustResult
+      let success = withUnsafeMutablePointer(to: &tr) { trPtr -> Bool in
+        if SecTrustEvaluate(myTrust, trPtr) != errSecSuccess {
+          return false
+        }
+        return true
+      }
+      if !success { return false }
+    }
+    if lastTrustResult == .proceed || lastTrustResult == .unspecified {
+        return false
+    }
+
+    print("TSSLSocketTransport: Unable to recover certificate trust failure")
+    return true
+  }
+  
+  public func isOpen() -> Bool {
+    return sd > 0
+  }
+}
+
+extension TSSLSocketTransport: StreamDelegate {
+  public func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
+    
+    switch eventCode {
+    case Stream.Event(): break
+    case Stream.Event.hasBytesAvailable: break
+    case Stream.Event.openCompleted: break
+    case Stream.Event.hasSpaceAvailable:
+      var proceed = false
+      var trustResult: SecTrustResultType = .invalid
+
+      var newPolicies: CFMutableArray?
+      
+      repeat {
+        let trust: SecTrust = aStream.property(forKey: .SSLPeerTrust) as! SecTrust
+        
+        // Add new policy to current list of policies
+        let policy = SecPolicyCreateSSL(false, sslHostname as CFString?)
+        var ppolicy = policy // mutable for pointer
+        let policies: UnsafeMutablePointer<CFArray?>? = nil
+        if SecTrustCopyPolicies(trust, policies!) != errSecSuccess {
+          break
+        }
+        withUnsafeMutablePointer(to: &ppolicy) { ptr in
+          newPolicies = CFArrayCreateMutableCopy(nil, 0, policies?.pointee)
+          CFArrayAppendValue(newPolicies, ptr)
+        }
+        
+        // update trust policies
+        if SecTrustSetPolicies(trust, newPolicies!) != errSecSuccess {
+          break
+        }
+        
+        // Evaluate the trust chain
+        let success = withUnsafeMutablePointer(to: &trustResult) { trustPtr -> Bool in
+          if SecTrustEvaluate(trust, trustPtr) != errSecSuccess {
+            return false
+          }
+          return true
+        }
+        
+        if !success {
+          break
+        }
+        
+        
+        switch trustResult {
+        case .proceed:      proceed = true
+        case .unspecified:  proceed = true
+        case .recoverableTrustFailure:
+          proceed = self.recoverFromTrustFailure(trust, lastTrustResult: trustResult)
+          
+        case .deny:         break
+        case .fatalTrustFailure: break
+        case .otherError:   break
+        case .invalid:      break
+        default: break
+        }
+      } while false
+  
+      if !proceed {
+        print("TSSLSocketTransport: Cannot trust certificate.  Result: \(trustResult)")
+        aStream.close()
+      }
+      
+    case Stream.Event.errorOccurred: break
+    case Stream.Event.endEncountered: break
+    default: break
+    }
+  }
+}
+#endif
diff --git a/lib/swift/Sources/TSSLSocketTransportError.swift b/lib/swift/Sources/TSSLSocketTransportError.swift
new file mode 100644
index 0000000..fda162b
--- /dev/null
+++ b/lib/swift/Sources/TSSLSocketTransportError.swift
@@ -0,0 +1,48 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+public struct TSSLSocketTransportError: TError {
+  public enum ErrorCode: TErrorCode {
+    case hostanameResolution(hostname: String)
+    case socketCreate(port: Int)
+    case connect
+  
+    public var thriftErrorCode: Int {
+      switch self {
+      case .hostanameResolution:  return -10000
+      case .socketCreate:         return -10001
+      case .connect:              return -10002
+      }
+    }
+  
+    public var description: String {
+      switch self {
+      case .hostanameResolution(let hostname):  return "Failed to resolve hostname: \(hostname)"
+      case .socketCreate(let port):             return "Could not create socket on port: \(port)"
+      case .connect:                            return "Connect error"
+      }
+    }
+  
+  }
+  public var error: ErrorCode = .connect
+  public var message: String?
+  public static var defaultCase: ErrorCode { return .connect }
+  
+  public init() { }
+}
diff --git a/lib/swift/Sources/TSerializable.swift b/lib/swift/Sources/TSerializable.swift
new file mode 100644
index 0000000..b45096b
--- /dev/null
+++ b/lib/swift/Sources/TSerializable.swift
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+
+public protocol TSerializable {
+  var hashValue: Int { get }
+
+  /// TType for instance
+  static var thriftType: TType { get }
+
+  /// Read TSerializable instance from Protocol
+  static func read(from proto: TProtocol) throws -> Self
+
+  /// Write TSerializable instance to Protocol
+  func write(to proto: TProtocol) throws
+
+}
+
+extension TSerializable {
+  public static func write(_ value: Self, to proto: TProtocol) throws {
+    try value.write(to: proto)
+  }
+
+  /// convenience for member access
+  public var thriftType: TType { return Self.thriftType }
+}
+
+public func ==<T>(lhs: T, rhs: T) -> Bool where T : TSerializable {
+  return lhs.hashValue == rhs.hashValue
+}
+
+/// Default read/write for primitave Thrift types:
+/// Bool, Int8 (byte), Int16, Int32, Int64, Double, String
+
+extension Bool : TSerializable {
+  public static var thriftType: TType { return .bool }
+
+  public static func read(from proto: TProtocol) throws -> Bool {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
+
+extension Int8 : TSerializable {
+  public static var thriftType: TType { return .i8 }
+
+  public static func read(from proto: TProtocol) throws -> Int8 {
+    return Int8(try proto.read() as UInt8)
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(UInt8(self))
+  }
+}
+
+extension Int16 : TSerializable {
+  public static var thriftType: TType { return .i16 }
+
+  public static func read(from proto: TProtocol) throws -> Int16 {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
+
+extension Int32 : TSerializable {
+  public static var thriftType: TType { return .i32 }
+
+  public static func read(from proto: TProtocol) throws -> Int32 {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
+
+
+extension Int64 : TSerializable {
+  public static var thriftType: TType { return .i64 }
+
+  public static func read(from proto: TProtocol) throws -> Int64 {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
+
+extension Double : TSerializable {
+  public static var thriftType: TType { return .double }
+
+  public static func read(from proto: TProtocol) throws -> Double {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
+
+extension String : TSerializable {
+  public static var thriftType: TType { return .string }
+
+  public static func read(from proto: TProtocol) throws -> String {
+    return try proto.read()
+  }
+
+  public func write(to proto: TProtocol) throws {
+    try proto.write(self)
+  }
+}
diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift
new file mode 100644
index 0000000..3e014c1
--- /dev/null
+++ b/lib/swift/Sources/TSet.swift
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+
+public struct TSet<Element : TSerializable & Hashable> : SetAlgebra, Hashable, Collection, ExpressibleByArrayLiteral, TSerializable {
+  /// Typealias for Storage type
+  typealias Storage = Set<Element>
+  
+  
+  /// Internal Storage used for TSet (Set\<Element\>)
+  internal var storage : Storage
+  
+  
+  /// Mark: Collection
+  
+  public typealias Indices = Storage.Indices
+  public typealias Index = Storage.Index
+  public typealias IndexDistance = Storage.IndexDistance
+  public typealias SubSequence = Storage.SubSequence
+  
+  
+  public var indices: Indices { return storage.indices }
+  
+  // Must implement isEmpty even though both SetAlgebra and Collection provide it due to their conflciting default implementations
+  public var isEmpty: Bool { return storage.isEmpty }
+  
+  public func distance(from start: Index, to end: Index) -> IndexDistance {
+    return storage.distance(from: start, to: end)
+  }
+  
+  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+    return storage.index(i, offsetBy: n)
+  }
+  
+  public func index(_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index) -> Index? {
+    return storage.index(i, offsetBy: n, limitedBy: limit)
+  }
+  
+  #if swift(>=3.2)
+  public subscript (position: Storage.Index) -> Element {
+      return storage[position]
+    }
+  #else
+  public subscript (position: Storage.Index) -> Element? {
+    return storage[position]
+  }
+  #endif
+  
+  /// Mark: SetAlgebra
+  internal init(storage: Set<Element>) {
+    self.storage = storage
+  }
+  
+  public func contains(_ member: Element) -> Bool {
+    return storage.contains(member)
+  }
+  
+  public mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) {
+    return storage.insert(newMember)
+  }
+  
+  public mutating func remove(_ member: Element) -> Element? {
+    return storage.remove(member)
+  }
+  
+  public func union(_ other: TSet<Element>) -> TSet {
+    return TSet(storage: storage.union(other.storage))
+  }
+  
+  public mutating func formIntersection(_ other: TSet<Element>) {
+    return storage.formIntersection(other.storage)
+  }
+  
+  public mutating func formSymmetricDifference(_ other: TSet<Element>) {
+    return storage.formSymmetricDifference(other.storage)
+  }
+  
+  public mutating func formUnion(_ other: TSet<Element>) {
+    return storage.formUnion(other.storage)
+  }
+  
+  public func intersection(_ other: TSet<Element>) -> TSet {
+    return TSet(storage: storage.intersection(other.storage))
+  }
+  
+  public func symmetricDifference(_ other: TSet<Element>) -> TSet {
+    return TSet(storage: storage.symmetricDifference(other.storage))
+  }
+  
+  public mutating func update(with newMember: Element) -> Element? {
+    return storage.update(with: newMember)
+  }
+  
+  /// Mark: IndexableBase
+  
+  public var startIndex: Index { return storage.startIndex }
+  public var endIndex: Index { return storage.endIndex }
+  public func index(after i: Index) -> Index {
+    return storage.index(after: i)
+  }
+
+  public func formIndex(after i: inout Storage.Index) {
+    storage.formIndex(after: &i)
+  }
+  
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    return storage[bounds]
+  }
+
+  
+  /// Mark: Hashable
+  public var hashValue : Int {
+    let prime = 31
+    var result = 1
+    for element in storage {
+      result = prime &* result &+ element.hashValue
+    }
+    return result
+  }
+  
+  /// Mark: TSerializable
+  public static var thriftType : TType { return .set }
+  
+  public init() {
+    storage = Storage()
+  }
+  
+  public init(arrayLiteral elements: Element...) {
+    self.storage = Storage(elements)
+  }
+  
+  public init<Source : Sequence>(_ sequence: Source) where Source.Iterator.Element == Element {
+    storage = Storage(sequence)
+  }
+  
+  public static func read(from proto: TProtocol) throws -> TSet {
+    let (elementType, size) = try proto.readSetBegin()
+    if elementType != Element.thriftType {
+      throw TProtocolError(error: .invalidData,
+                           extendedError: .unexpectedType(type: elementType))
+    }
+    var set = TSet()
+    for _ in 0..<size {
+      let element = try Element.read(from: proto)
+      set.storage.insert(element)
+    }
+    try proto.readSetEnd()
+    return set
+  }
+  
+  public func write(to proto: TProtocol) throws {
+    try proto.writeSetBegin(elementType: Element.thriftType, size: Int32(self.count))
+    for element in self.storage {
+      try Element.write(element, to: proto)
+    }
+    try proto.writeSetEnd()
+  }
+}
+
+extension TSet: CustomStringConvertible, CustomDebugStringConvertible {
+  public var description : String {
+    return storage.description
+  }
+  public var debugDescription : String {
+    return storage.debugDescription
+  }
+  
+}
+
+public func ==<Element>(lhs: TSet<Element>, rhs: TSet<Element>) -> Bool {
+  return lhs.storage == rhs.storage
+}
diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift
new file mode 100644
index 0000000..0224e67
--- /dev/null
+++ b/lib/swift/Sources/TSocketServer.swift
@@ -0,0 +1,149 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+  import Darwin
+#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
+  import Glibc
+  import Dispatch
+#endif
+
+import Foundation
+import CoreFoundation
+
+public let TSocketServerClientConnectionFinished = "TSocketServerClientConnectionFinished"
+public let TSocketServerProcessorKey = "TSocketServerProcessor"
+public let TSocketServerTransportKey = "TSocketServerTransport"
+
+class TSocketServer<InProtocol: TProtocol, OutProtocol: TProtocol, Processor: TProcessor, Service> where Processor.Service == Service {
+  var socketFileHandle: FileHandle
+  var processingQueue =  DispatchQueue(label: "TSocketServer.processing",
+                                       qos: .background,
+                                       attributes: .concurrent)
+  var serviceHandler: Service
+
+  public init(port: Int,
+              service: Service,
+              inProtocol: InProtocol.Type,
+              outProtocol: OutProtocol.Type,
+              processor: Processor.Type) throws {
+    // set service handler
+    self.serviceHandler = service
+
+    // create a socket
+    var fd: Int32 = -1
+    #if os(Linux)
+      let sock = CFSocketCreate(kCFAllocatorDefault, PF_INET, Int32(SOCK_STREAM.rawValue), Int32(IPPROTO_TCP), 0, nil, nil)
+    #else
+      let sock = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, nil, nil)
+    #endif
+    if sock != nil {
+      CFSocketSetSocketFlags(sock, CFSocketGetSocketFlags(sock) & ~kCFSocketCloseOnInvalidate)
+
+      fd = CFSocketGetNative(sock)
+      var yes = 1
+      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, UInt32(MemoryLayout<Int>.size))
+
+      #if os(Linux)
+        var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
+                               sin_port: in_port_t(port.bigEndian),
+                               sin_addr: in_addr(s_addr: in_addr_t(0)),
+                               sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+      #else
+        var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
+                               sin_family: sa_family_t(AF_INET),
+                               sin_port: in_port_t(port.bigEndian),
+                               sin_addr: in_addr(s_addr: in_addr_t(0)),
+                               sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+      #endif
+
+      let ptr = withUnsafePointer(to: &addr) {
+        return UnsafePointer<UInt8>(OpaquePointer($0))
+      }
+
+      let address = Data(bytes: ptr, count: MemoryLayout<sockaddr_in>.size)
+
+      let cfaddr = address.withUnsafeBytes {
+        CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0, address.count, nil)
+      }
+      if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess {
+        CFSocketInvalidate(sock)
+        print("TSocketServer: Could not bind to address")
+        throw TTransportError(error: .notOpen, message: "Could not bind to address")
+      }
+
+    } else {
+      print("TSocketServer: No server socket")
+      throw TTransportError(error: .notOpen, message: "Could not create socket")
+    }
+
+    // wrap it in a file handle so we can get messages from it
+    socketFileHandle = FileHandle(fileDescriptor: fd, closeOnDealloc: true)
+
+    // throw away our socket
+    CFSocketInvalidate(sock)
+
+    // register for notifications of accepted incoming connections
+    _ = NotificationCenter.default.addObserver(forName: .NSFileHandleConnectionAccepted,
+                                               object: nil, queue: nil) {
+                                                [weak self] notification in
+                                                guard let strongSelf = self else { return }
+                                                strongSelf.connectionAccepted(strongSelf.socketFileHandle)
+
+    }
+
+    // tell socket to listen
+    socketFileHandle.acceptConnectionInBackgroundAndNotify()
+
+    print("TSocketServer: Listening on TCP port \(port)")
+  }
+
+  deinit {
+    NotificationCenter.default.removeObserver(self)
+  }
+
+  func connectionAccepted(_ socket: FileHandle) {
+    // Now that we have a client connected, handle the request on queue
+    processingQueue.async {
+      self.handleClientConnection(socket)
+    }
+  }
+
+  func handleClientConnection(_ clientSocket: FileHandle) {
+
+    let transport = TFileHandleTransport(fileHandle: clientSocket)
+    let processor = Processor(service: serviceHandler)
+
+    let inProtocol = InProtocol(on: transport)
+    let outProtocol = OutProtocol(on: transport)
+
+    do {
+      try processor.process(on: inProtocol, outProtocol: outProtocol)
+    } catch let error {
+      print("Error processign request: \(error)")
+    }
+    DispatchQueue.main.async {
+      NotificationCenter.default
+        .post(name: Notification.Name(rawValue: TSocketServerClientConnectionFinished),
+              object: self,
+              userInfo: [TSocketServerProcessorKey: processor,
+                         TSocketServerTransportKey: transport])
+    }
+  }
+}
diff --git a/lib/swift/Sources/TSocketTransport.swift b/lib/swift/Sources/TSocketTransport.swift
new file mode 100644
index 0000000..891bd27
--- /dev/null
+++ b/lib/swift/Sources/TSocketTransport.swift
@@ -0,0 +1,210 @@
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+  import Darwin
+#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
+  import Glibc
+  import Dispatch
+#endif
+
+import Foundation
+import CoreFoundation
+
+private struct Sys {
+  #if os(Linux)
+  static let read = Glibc.read
+  static let write = Glibc.write
+  static let close = Glibc.close
+  #else
+  static let read = Darwin.read
+  static let write = Darwin.write
+  static let close = Darwin.close
+  #endif
+}
+
+extension in_addr {
+  public init?(hostent: hostent?) {
+    guard let host = hostent, host.h_addr_list != nil, host.h_addr_list.pointee != nil else {
+      return nil
+    }
+    self.init()
+    memcpy(&self, host.h_addr_list.pointee!, Int(host.h_length))
+    
+  }
+}
+
+
+#if os(Linux)
+  /// TCFSocketTransport currently unavailable
+  /// remove comments and build to see why/fix
+  /// currently CF[Read|Write]Stream's can't cast to [Input|Output]Streams which breaks thigns
+#else
+extension Stream.PropertyKey {
+  static let SSLPeerTrust = Stream.PropertyKey(kCFStreamPropertySSLPeerTrust as String)
+}
+
+/// TCFSocketTransport, uses CFSockets and (NS)Stream's
+public class TCFSocketTransport: TStreamTransport {
+    public init?(hostname: String, port: Int, secure: Bool = false) {
+    
+    var inputStream: InputStream
+    var outputStream: OutputStream
+    
+    var readStream:  Unmanaged<CFReadStream>?
+    var writeStream:  Unmanaged<CFWriteStream>?
+    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
+                                       hostname as CFString!,
+                                       UInt32(port),
+                                       &readStream,
+                                       &writeStream)
+    
+    if let readStream = readStream?.takeRetainedValue(),
+      let writeStream = writeStream?.takeRetainedValue() {
+        CFReadStreamSetProperty(readStream, .shouldCloseNativeSocket, kCFBooleanTrue)
+        CFWriteStreamSetProperty(writeStream, .shouldCloseNativeSocket, kCFBooleanTrue)
+      
+        if secure {
+            CFReadStreamSetProperty(readStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL._rawValue)
+            CFWriteStreamSetProperty(writeStream, .socketSecurityLevel, StreamSocketSecurityLevel.negotiatedSSL._rawValue)
+        }
+
+      inputStream = readStream as InputStream
+      inputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
+      inputStream.open()
+      
+      outputStream = writeStream as OutputStream
+      outputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
+      outputStream.open()
+      
+    } else {
+      
+      if readStream != nil {
+        readStream?.release()
+      }
+      if writeStream != nil {
+        writeStream?.release()
+      }
+      super.init(inputStream: nil, outputStream: nil)
+      return nil
+    }
+    
+    super.init(inputStream: inputStream, outputStream: outputStream)
+    
+    self.input?.delegate = self
+    self.output?.delegate = self
+  }
+}
+
+extension TCFSocketTransport: StreamDelegate { }
+#endif
+
+
+/// TSocketTransport, posix sockets.  Supports IPv4 only for now
+public class TSocketTransport : TTransport {
+  public var socketDescriptor: Int32
+  
+  
+  
+  /// Initialize from an already set up socketDescriptor.
+  /// Expects socket thats already bound/connected (i.e. from listening)
+  ///
+  /// - parameter socketDescriptor: posix socket descriptor (Int32)
+  public init(socketDescriptor: Int32) {
+    self.socketDescriptor = socketDescriptor
+  }
+  
+  
+  public convenience init(hostname: String, port: Int) throws {
+    guard let hp = gethostbyname(hostname.cString(using: .utf8)!)?.pointee,
+      let hostAddr = in_addr(hostent: hp) else {
+        throw TTransportError(error: .unknown, message: "Invalid address: \(hostname)")
+    }
+    
+    
+    
+    #if os(Linux)
+      let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
+      var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
+                             sin_port: in_port_t(htons(UInt16(port))),
+                             sin_addr: hostAddr,
+                             sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+    #else
+      let sock = socket(AF_INET, SOCK_STREAM, 0)
+      
+      var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
+                             sin_family: sa_family_t(AF_INET),
+                             sin_port: in_port_t(htons(UInt16(port))),
+                             sin_addr: in_addr(s_addr: in_addr_t(0)),
+                             sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
+      
+    #endif
+    
+    let addrPtr = withUnsafePointer(to: &addr){ UnsafePointer<sockaddr>(OpaquePointer($0)) }
+    
+    let connected = connect(sock, addrPtr, UInt32(MemoryLayout<sockaddr_in>.size))
+    if connected != 0 {
+      throw TTransportError(error: .notOpen, message: "Error binding to host: \(hostname) \(port)")
+    }
+    
+    self.init(socketDescriptor: sock)
+  }
+  
+  deinit {
+    close()
+  }
+  
+  public func readAll(size: Int) throws -> Data {
+    var out = Data()
+    while out.count < size {
+      out.append(try self.read(size: size))
+    }
+    return out
+  }
+  
+  public func read(size: Int) throws -> Data {
+    var buff = Array<UInt8>.init(repeating: 0, count: size)
+    let readBytes = Sys.read(socketDescriptor, &buff, size)
+    
+    return Data(bytes: buff[0..<readBytes])
+  }
+  
+  public func write(data: Data) {
+    var bytesToWrite = data.count
+    var writeBuffer = data
+    while bytesToWrite > 0 {
+      let written = writeBuffer.withUnsafeBytes {
+        Sys.write(socketDescriptor, $0, writeBuffer.count)
+      }
+      writeBuffer = writeBuffer.subdata(in: written ..< writeBuffer.count)
+      bytesToWrite -= written
+    }
+  }
+  
+  public func flush() throws {
+    // nothing to do
+  }
+  
+  public func close() {
+    shutdown(socketDescriptor, Int32(SHUT_RDWR))
+    _ = Sys.close(socketDescriptor)
+  }
+}
diff --git a/lib/swift/Sources/TStreamTransport.swift b/lib/swift/Sources/TStreamTransport.swift
new file mode 100644
index 0000000..26bc1b8
--- /dev/null
+++ b/lib/swift/Sources/TStreamTransport.swift
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Foundation
+import CoreFoundation
+
+#if os(Linux)
+  /// Currently unavailable in Linux
+  /// Remove comments and build to fix
+  /// Currently kConstants for CFSockets don't exist in linux and not all have been moved
+  /// to property structs yet
+#else
+  // Must inherit NSObject for NSStreamDelegate conformance
+  public class TStreamTransport : NSObject, TTransport {
+    public var input: InputStream? = nil
+    public var output: OutputStream? = nil
+    
+    public init(inputStream: InputStream?, outputStream: OutputStream?) {
+      input   = inputStream
+      output  = outputStream
+    }
+    
+    public convenience init(inputStream: InputStream?) {
+      self.init(inputStream: inputStream, outputStream: nil)
+    }
+    
+    public convenience init(outputStream: OutputStream?) {
+      self.init(inputStream: nil, outputStream: outputStream)
+    }
+    
+    deinit {
+      close()
+    }
+    
+    public func readAll(size: Int) throws -> Data {
+      guard let input = input else {
+        throw TTransportError(error: .unknown)
+      }
+      
+      var read = Data()
+      while read.count < size {
+        var buffer = Array<UInt8>(repeating: 0, count: size - read.count)
+        
+        let bytesRead = buffer.withUnsafeMutableBufferPointer { bufferPtr in
+          return input.read(bufferPtr.baseAddress!, maxLength: size - read.count)
+        }
+        
+        if bytesRead <= 0 {
+          throw TTransportError(error: .notOpen)
+        }
+        read.append(Data(bytes: buffer))
+      }
+      return read
+    }
+    
+    public func read(size: Int) throws -> Data {
+      guard let input = input else {
+        throw TTransportError(error: .unknown)
+      }
+      
+      var read = Data()
+      while read.count < size {
+        var buffer = Array<UInt8>(repeating: 0, count: size - read.count)
+        let bytesRead = buffer.withUnsafeMutableBufferPointer {
+          input.read($0.baseAddress!, maxLength: size - read.count)
+        }
+        
+        if bytesRead <= 0 {
+          break
+        }
+        
+        read.append(Data(bytes: buffer))
+      }
+      return read
+    }
+    
+    public func write(data: Data) throws {
+      guard let output = output else {
+        throw TTransportError(error: .unknown)
+      }
+      
+      var bytesWritten = 0
+      while bytesWritten < data.count {
+        bytesWritten = data.withUnsafeBytes {
+          return output.write($0, maxLength: data.count)
+        }
+        
+        if bytesWritten == -1 {
+          throw TTransportError(error: .notOpen)
+        } else if bytesWritten == 0 {
+          throw TTransportError(error: .endOfFile)
+        }
+      }
+    }
+    
+    
+    public func flush() throws {
+      return
+    }
+    
+    public func close() {
+      
+      if input != nil {
+        // Close and reset inputstream
+        if let cf: CFReadStream = input {
+          CFReadStreamSetProperty(cf, .shouldCloseNativeSocket, kCFBooleanTrue)
+        }
+        
+        input?.delegate = nil
+        input?.close()
+        input?.remove(from: .current, forMode: .defaultRunLoopMode)
+        input = nil
+      }
+      
+      if output != nil {
+        // Close and reset output stream
+        if let cf: CFWriteStream = output {
+          CFWriteStreamSetProperty(cf, .shouldCloseNativeSocket, kCFBooleanTrue)
+        }
+        output?.delegate = nil
+        output?.close()
+        output?.remove(from: .current, forMode: .defaultRunLoopMode)
+        output = nil
+      }
+    }
+  }
+#endif
diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift
new file mode 100644
index 0000000..f172a32
--- /dev/null
+++ b/lib/swift/Sources/TStruct.swift
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+/// Protocol for Generated Structs to conform to
+/// Dictionary maps field names to internal IDs and uses Reflection
+/// to iterate through all fields.  
+/// `writeFieldValue(_:name:type:id:)` calls `TSerializable.write(to:)` internally
+/// giving a nice recursive behavior for nested TStructs, TLists, TMaps, and TSets
+public protocol TStruct : TSerializable {
+  static var fieldIds: [String: Int32] { get }
+  static var structName: String { get }
+}
+
+public extension TStruct {
+  public static var fieldIds: [String: (id: Int32, type: TType)] { return [:] }
+  public static var thriftType: TType { return .struct }
+  
+  public func write(to proto: TProtocol) throws {
+    // Write struct name first
+    try proto.writeStructBegin(name: Self.structName)
+    
+    try self.forEach { name, value, id in
+      // Write to protocol
+      try proto.writeFieldValue(value, name: name,
+                                type: value.thriftType, id: id)
+    }
+    try proto.writeFieldStop()
+    try proto.writeStructEnd()
+  }
+  
+  public var hashValue: Int {
+    let prime = 31
+    var result = 1
+    self.forEach { _, value, _ in
+      result = prime &* result &+ (value.hashValue)
+    }
+    return result
+  }
+  
+  /// Provides a block for handling each (available) thrift property using reflection
+  /// Caveat: Skips over optional values
+  
+  
+  /// Provides a block for handling each (available) thrift property using reflection
+  ///
+  /// - parameter block: block for handling property
+  ///
+  /// - throws: rethrows any Error thrown in block
+  private func forEach(_ block: (_ name: String, _ value: TSerializable, _ id: Int32) throws -> Void) rethrows {
+    // Mirror the object, getting (name: String?, value: Any) for every property
+    let mirror = Mirror(reflecting: self)
+    
+    // Iterate through all children, ignore empty property names
+    for (propName, propValue) in mirror.children {
+      guard let propName = propName else { continue }
+
+      if let tval = unwrap(any: propValue) as? TSerializable, let id = Self.fieldIds[propName] {
+        try block(propName, tval, id)
+      }
+    }
+  }
+  
+  
+  /// Any can mysteriously be an Optional<Any> at the same time,
+  /// this checks and always returns Optional<Any> without double wrapping
+  /// we then try to bind value as TSerializable to ignore any extension properties
+  /// and the like and verify the property exists and grab the Thrift
+  /// property ID at the same time
+  ///
+  /// - parameter any: Any instance to attempt to unwrap
+  ///
+  /// - returns: Unwrapped Any as Optional<Any>
+  private func unwrap(any: Any) -> Any? {
+    let mi = Mirror(reflecting: any)
+    
+    if mi.displayStyle != .optional { return any }
+    if mi.children.count == 0 { return nil }
+    
+    let (_, some) = mi.children.first!
+    return some
+  }
+}
+
diff --git a/lib/swift/Sources/TTransport.swift b/lib/swift/Sources/TTransport.swift
new file mode 100644
index 0000000..e82bbe1
--- /dev/null
+++ b/lib/swift/Sources/TTransport.swift
@@ -0,0 +1,64 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation
+
+public protocol TTransport {
+  
+  // Required
+  func read(size: Int) throws -> Data
+  func write(data: Data) throws
+  func flush() throws
+
+  // Optional (default provided)
+  func readAll(size: Int) throws -> Data
+  func isOpen() throws -> Bool
+  func open() throws
+  func close() throws
+}
+
+public extension TTransport {
+  func isOpen() throws -> Bool { return true }
+  func open() throws { }
+  func close() throws { }
+  
+  func readAll(size: Int) throws -> Data {
+    var buff = Data()
+    var have = 0
+    while have < size {
+      let chunk = try self.read(size: size - have)
+      have += chunk.count
+      buff.append(chunk)
+      if chunk.count == 0 {
+        throw TTransportError(error: .endOfFile)
+      }
+    }
+    return buff
+  }
+}
+
+public protocol TAsyncTransport : TTransport {
+  // Factory
+  func flush(_ completion: @escaping (TAsyncTransport, Error?) ->())
+}
+
+public protocol TAsyncTransportFactory {
+  associatedtype Transport : TAsyncTransport
+  func newTransport() -> Transport
+}
diff --git a/lib/swift/Sources/TTransportError.swift b/lib/swift/Sources/TTransportError.swift
new file mode 100644
index 0000000..3fd0059
--- /dev/null
+++ b/lib/swift/Sources/TTransportError.swift
@@ -0,0 +1,86 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+public struct TTransportError: TError {
+  public enum ErrorCode: TErrorCode {
+    case unknown
+    case notOpen
+    case alreadyOpen
+    case timedOut
+    case endOfFile
+    case negativeSize
+    case sizeLimit(limit: Int, got: Int)
+    
+    public var thriftErrorCode: Int {
+      switch self {
+      case .unknown:      return 0
+      case .notOpen:      return 1
+      case .alreadyOpen:  return 2
+      case .timedOut:     return 3
+      case .endOfFile:    return 4
+      case .negativeSize: return 5
+      case .sizeLimit:    return 6
+      }
+    }
+    public var description: String {
+      switch self {
+      case .unknown:      return "Unknown TTransportError"
+      case .notOpen:      return "Not Open"
+      case .alreadyOpen:  return "Already Open"
+      case .timedOut:     return "Timed Out"
+      case .endOfFile:    return "End Of File"
+      case .negativeSize: return "Negative Size"
+      case .sizeLimit(let limit, let got):
+        return "Message exceeds size limit of \(limit) (received: \(got)"
+      }
+    }
+  }
+  public var error: ErrorCode = .unknown
+  public var message: String? = nil
+  public static var defaultCase: ErrorCode { return .unknown }
+  
+  public init() { }
+
+}
+
+/// THTTPTransportError
+///
+/// Error's thrown on HTTP Transport
+public struct THTTPTransportError: TError {
+  public enum ErrorCode: TErrorCode {
+    case invalidResponse
+    case invalidStatus(statusCode: Int)
+    case authentication
+    
+    public var description: String {
+      switch self {
+      case .invalidResponse:                return "Invalid HTTP Response"
+      case .invalidStatus(let statusCode):  return "Invalid HTTP Status Code (\(statusCode))"
+      case .authentication:                 return "Authentication Error"
+      }
+    }
+    public var thriftErrorCode: Int { return 0 }
+  }
+  public var error: ErrorCode = .invalidResponse
+  public var message: String? = nil
+  public static var defaultCase: ErrorCode { return .invalidResponse }
+  
+  public init() { }
+}
+
diff --git a/lib/swift/Sources/TWrappedProtocol.swift b/lib/swift/Sources/TWrappedProtocol.swift
new file mode 100644
index 0000000..8e8577b
--- /dev/null
+++ b/lib/swift/Sources/TWrappedProtocol.swift
@@ -0,0 +1,208 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import Foundation // For (NS)Data
+
+
+/// Generic protocol, implementes TProtocol and wraps a concrete protocol.
+/// Useful for generically subclassing protocols to override specific methods 
+/// (i.e. TMultiplexedProtocol)
+open class TWrappedProtocol<Protocol: TProtocol> : TProtocol {
+  var concreteProtocol: Protocol
+  
+  public var transport: TTransport {
+    get {
+      return concreteProtocol.transport
+    }
+    set {
+      concreteProtocol.transport = newValue
+    }
+  }
+
+  public required init(on transport: TTransport) {
+    self.concreteProtocol = Protocol(on: transport)
+  }
+  
+  // Read methods
+  
+  public func readMessageBegin() throws -> (String, TMessageType, Int32) {
+    return try concreteProtocol.readMessageBegin()
+  }
+  
+  public func readMessageEnd() throws {
+    try concreteProtocol.readMessageEnd()
+  }
+  
+  public func readStructBegin() throws -> String {
+    return try concreteProtocol.readStructBegin()
+  }
+  
+  public func readStructEnd() throws {
+    try concreteProtocol.readStructEnd()
+  }
+  
+  public func readFieldBegin() throws -> (String, TType, Int32) {
+    return try concreteProtocol.readFieldBegin()
+  }
+  
+  public func readFieldEnd() throws {
+    try concreteProtocol.readFieldEnd()
+  }
+  
+  public func readMapBegin() throws -> (TType, TType, Int32) {
+    return try concreteProtocol.readMapBegin()
+  }
+  
+  public func readMapEnd() throws {
+    try concreteProtocol.readMapEnd()
+  }
+  
+  public func readSetBegin() throws -> (TType, Int32) {
+    return try concreteProtocol.readSetBegin()
+  }
+  
+  public func readSetEnd() throws {
+    try concreteProtocol.readSetEnd()
+  }
+  
+  public func readListBegin() throws -> (TType, Int32) {
+    return try concreteProtocol.readListBegin()
+  }
+  
+  public func readListEnd() throws {
+    try concreteProtocol.readListEnd()
+  }
+  
+  public func read() throws -> String {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Bool {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> UInt8 {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Int16 {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Int32 {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Int64 {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Double {
+    return try concreteProtocol.read()
+  }
+  
+  public func read() throws -> Data {
+    return try concreteProtocol.read()
+  }
+  
+  // Write methods
+  
+  public func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws {
+    return try concreteProtocol.writeMessageBegin(name: name, type: messageType, sequenceID: sequenceID)
+  }
+  
+  public func writeMessageEnd() throws {
+    try concreteProtocol.writeMessageEnd()
+  }
+  
+  public func writeStructBegin(name: String) throws {
+    try concreteProtocol.writeStructBegin(name: name)
+  }
+  
+  public func writeStructEnd() throws {
+    try concreteProtocol.writeStructEnd()
+  }
+  
+  public func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws {
+    try concreteProtocol.writeFieldBegin(name: name, type: fieldType, fieldID: fieldID)
+  }
+  
+  public func writeFieldStop() throws {
+    try concreteProtocol.writeFieldStop()
+  }
+  
+  public func writeFieldEnd() throws {
+    try concreteProtocol.writeFieldEnd()
+  }
+  
+  public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws {
+    try concreteProtocol.writeMapBegin(keyType: keyType, valueType: valueType, size: size)
+  }
+  
+  public func writeMapEnd() throws {
+    try concreteProtocol.writeMapEnd()
+  }
+  
+  public func writeSetBegin(elementType: TType, size: Int32) throws {
+    try concreteProtocol.writeSetBegin(elementType: elementType, size: size)
+  }
+  
+  public func writeSetEnd() throws {
+    try concreteProtocol.writeSetEnd()
+  }
+  
+  public func writeListBegin(elementType: TType, size: Int32) throws {
+    try concreteProtocol.writeListBegin(elementType: elementType, size: size)
+  }
+  
+  public func writeListEnd() throws {
+    try concreteProtocol.writeListEnd()
+  }
+  public func write(_ value: String) throws {
+    try concreteProtocol.write(value)
+  }
+  
+  public func write(_ value: Bool) throws {
+    try concreteProtocol.write(value)
+  }
+  
+  public func write(_ value: UInt8) throws {
+    try concreteProtocol.write(value)
+  }
+
+  public func write(_ value: Int16) throws {
+    try concreteProtocol.write(value)
+  }
+  
+  public func write(_ value: Int32) throws {
+    try concreteProtocol.write(value)
+  }
+  
+  public func write(_ value: Int64) throws {
+    try concreteProtocol.write(value)
+  }
+  
+  public func write(_ value: Double) throws {
+    try concreteProtocol.write(value)
+  }
+
+  public func write(_ data: Data) throws {
+    try concreteProtocol.write(data)
+  }
+}
diff --git a/lib/swift/Sources/Thrift.swift b/lib/swift/Sources/Thrift.swift
new file mode 100644
index 0000000..afa3096
--- /dev/null
+++ b/lib/swift/Sources/Thrift.swift
@@ -0,0 +1,3 @@
+class Thrift {
+	let version = "0.0.1"
+}
diff --git a/lib/swift/Tests/LinuxMain.swift b/lib/swift/Tests/LinuxMain.swift
new file mode 100644
index 0000000..288fec9
--- /dev/null
+++ b/lib/swift/Tests/LinuxMain.swift
@@ -0,0 +1,8 @@
+import XCTest
+@testable import ThriftTests
+
+XCTMain([
+     testCase(ThriftTests.allTests),
+     testCase(TBinaryProtocolTests.allTests),
+     testCase(TCompactProtocolTests.allTests),
+])
diff --git a/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift b/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift
new file mode 100644
index 0000000..f0e48b9
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift
@@ -0,0 +1,146 @@
+//
+//  TBinaryProtocolTests.swift
+//  Thrift
+//
+//  Created by Christopher Simpson on 8/18/16.
+//
+//
+
+import XCTest
+import Foundation
+@testable import Thrift
+
+
+/// Testing Binary protocol read/write against itself
+/// Uses separate read/write transport/protocols 
+class TBinaryProtocolTests: XCTestCase {
+  var transport: TMemoryBufferTransport = TMemoryBufferTransport(flushHandler: {
+    $0.reset(readBuffer: $1)
+  })
+  
+  var proto: TBinaryProtocol!
+  
+  override func setUp() {
+    super.setUp()
+    proto = TBinaryProtocol(on: transport)
+    transport.reset()
+  }
+  
+  override func tearDown() {
+    super.tearDown()
+    transport.reset()
+  }
+  
+  func testInt8WriteRead() {
+    let writeVal: UInt8 = 250
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: UInt8 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with UInt8, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt16WriteRead() {
+
+    let writeVal: Int16 = 12312
+    try? proto.write(writeVal)
+    try? transport.flush()
+    let readVal: Int16 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int16, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt32WriteRead() {
+    let writeVal: Int32 = 2029234
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Int32 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int32, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt64WriteRead() {
+    let writeVal: Int64 = 234234981374134
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Int64 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int64, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testDoubleWriteRead() {
+    let writeVal: Double = 3.1415926
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Double = (try? proto.read()) ?? 0.0
+    XCTAssertEqual(writeVal, readVal, "Error with Double, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testBoolWriteRead() {
+    let writeVal: Bool = true
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Bool = (try? proto.read()) ?? false
+    XCTAssertEqual(writeVal, readVal, "Error with Bool, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testStringWriteRead() {
+    let writeVal: String = "Hello World"
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: String!
+    do {
+      readVal = try proto.read()
+    } catch let error {
+      XCTAssertFalse(true, "Error reading \(error)")
+      return
+    }
+    
+    XCTAssertEqual(writeVal, readVal, "Error with String, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testDataWriteRead() {
+    let writeVal: Data = "Data World".data(using: .utf8)!
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Data = (try? proto.read()) ?? "Goodbye World".data(using: .utf8)!
+    XCTAssertEqual(writeVal, readVal, "Error with Data, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testStructWriteRead() {
+    let msg = "Test Protocol Error"
+    let writeVal = TApplicationError(error: .protocolError, message: msg)
+    do {
+      try writeVal.write(to: proto)
+      try? transport.flush()
+
+    } catch let error {
+      XCTAssertFalse(true, "Caught Error attempting to write \(error)")
+    }
+    
+    do {
+      let readVal = try TApplicationError.read(from: proto)
+      XCTAssertEqual(readVal.error.thriftErrorCode, writeVal.error.thriftErrorCode, "Error case mismatch, expected \(readVal.error) got \(writeVal.error)")
+      XCTAssertEqual(readVal.message, writeVal.message, "Error message mismatch, expected \(readVal.message) got \(writeVal.message)")
+    } catch let error {
+      XCTAssertFalse(true, "Caught Error attempting to read \(error)")
+    }
+  }
+  
+  static var allTests : [(String, (TBinaryProtocolTests) -> () throws -> Void)] {
+    return [
+      ("testInt8WriteRead", testInt8WriteRead),
+      ("testInt16WriteRead", testInt16WriteRead),
+      ("testInt32WriteRead", testInt32WriteRead),
+      ("testInt64WriteRead", testInt64WriteRead),
+      ("testDoubleWriteRead", testDoubleWriteRead),
+      ("testBoolWriteRead", testBoolWriteRead),
+      ("testStringWriteRead", testStringWriteRead),
+      ("testDataWriteRead", testDataWriteRead),
+      ("testStructWriteRead", testStructWriteRead)
+    ]
+  }
+}
diff --git a/lib/swift/Tests/ThriftTests/TCompactProtocolTests.swift b/lib/swift/Tests/ThriftTests/TCompactProtocolTests.swift
new file mode 100644
index 0000000..ccc32aa
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/TCompactProtocolTests.swift
@@ -0,0 +1,144 @@
+//
+//  TCompactProtocolTests.swift
+//  Thrift
+//
+//  Created by Christopher Simpson on 8/19/16.
+//
+//
+
+import XCTest
+import Foundation
+@testable import Thrift
+
+
+/// Testing Binary protocol read/write against itself
+/// Uses separate read/write transport/protocols
+class TCompactProtocolTests: XCTestCase {
+  var transport: TMemoryBufferTransport = TMemoryBufferTransport(flushHandler: {
+    $0.reset(readBuffer: $1)
+  })
+  var proto: TCompactProtocol!
+  
+  override func setUp() {
+    super.setUp()
+    proto = TCompactProtocol(on: transport)
+    transport.reset()
+  }
+  
+  override func tearDown() {
+    super.tearDown()
+    transport.reset()
+  }
+  
+  func testInt8WriteRead() {
+    let writeVal: UInt8 = 250
+    try? proto.write(writeVal)
+    try? transport.flush()
+    let readVal: UInt8 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with UInt8, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt16WriteRead() {
+    let writeVal: Int16 = 12312
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Int16 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int16, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt32WriteRead() {
+    let writeVal: Int32 = 2029234
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Int32 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int32, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testInt64WriteRead() {
+    let writeVal: Int64 = 234234981374134
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Int64 = (try? proto.read()) ?? 0
+    XCTAssertEqual(writeVal, readVal, "Error with Int64, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testDoubleWriteRead() {
+    let writeVal: Double = 3.1415926
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Double = (try? proto.read()) ?? 0.0
+    XCTAssertEqual(writeVal, readVal, "Error with Double, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testBoolWriteRead() {
+    let writeVal: Bool = true
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Bool = (try? proto.read()) ?? false
+    XCTAssertEqual(writeVal, readVal, "Error with Bool, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testStringWriteRead() {
+    let writeVal: String = "Hello World"
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: String!
+    do {
+      readVal = try proto.read()
+    } catch let error {
+      XCTAssertFalse(true, "Error reading \(error)")
+      return
+    }
+    
+    XCTAssertEqual(writeVal, readVal, "Error with String, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testDataWriteRead() {
+    let writeVal: Data = "Data World".data(using: .utf8)!
+    try? proto.write(writeVal)
+    try? transport.flush()
+
+    let readVal: Data = (try? proto.read()) ?? "Goodbye World".data(using: .utf8)!
+    XCTAssertEqual(writeVal, readVal, "Error with Data, wrote \(writeVal) but read \(readVal)")
+  }
+  
+  func testStructWriteRead() {
+    let msg = "Test Protocol Error"
+    let writeVal = TApplicationError(error: .protocolError, message: msg)
+    do {
+      try writeVal.write(to: proto)
+      try transport.flush()
+
+    } catch let error {
+      XCTAssertFalse(true, "Caught Error attempting to write \(error)")
+    }
+    
+    do {
+      let readVal = try TApplicationError.read(from: proto)
+      XCTAssertEqual(readVal.error.thriftErrorCode, writeVal.error.thriftErrorCode, "Error case mismatch, expected \(readVal.error) got \(writeVal.error)")
+      XCTAssertEqual(readVal.message, writeVal.message, "Error message mismatch, expected \(readVal.message) got \(writeVal.message)")
+    } catch let error {
+      XCTAssertFalse(true, "Caught Error attempting to read \(error)")
+    }
+  }
+  
+  static var allTests : [(String, (TCompactProtocolTests) -> () throws -> Void)] {
+    return [
+      ("testInt8WriteRead", testInt8WriteRead),
+      ("testInt16WriteRead", testInt16WriteRead),
+      ("testInt32WriteRead", testInt32WriteRead),
+      ("testInt64WriteRead", testInt64WriteRead),
+      ("testDoubleWriteRead", testDoubleWriteRead),
+      ("testBoolWriteRead", testBoolWriteRead),
+      ("testStringWriteRead", testStringWriteRead),
+      ("testDataWriteRead", testDataWriteRead),
+      ("testStructWriteRead", testStructWriteRead)
+    ]
+  }
+}
diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift
new file mode 100644
index 0000000..0c81330
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/ThriftTests.swift
@@ -0,0 +1,18 @@
+import XCTest
+@testable import Thrift
+
+class ThriftTests: XCTestCase {
+  func testVersion() {
+    XCTAssertEqual(Thrift().version, "0.0.1")
+  }
+  
+  func test_in_addr_extension() {
+    
+  }
+  
+  static var allTests : [(String, (ThriftTests) -> () throws -> Void)] {
+    return [
+      ("testVersion", testVersion),
+    ]
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
jking@apache.org.